STM32F4XX的I2C下的DMA控制代码
#include <stm32f4xx.h>#define IICRx_COUNTER 3 //I2C DMA接收数据(主机写)字节数,u16step + u8dirspd
#define IICTx_COUNTER 8 //I2C DMA发送数据(主机读)字节数,u8temp + u16yrstep + u16zrstep + u16arstep + u8temp,第一个temp为了避开DMA首字节缓冲,最后一个temp为了配合CH341的多一个数据
u8 IIC_ADDRESS; //确定IO口后再做硬件地址
volatile u8 IIC_DMA_RxBuf = {0,0,0};
volatile u8 IIC_DMA_TxBuf = {0,0,0,0,0,0,0,0};
/*
typedef struct
{
volatile u32 temp; //本次行程中步数计数器
volatile u32 step; //本次行程总步数(长行程轴步数)
volatile u32 add; //加速点
volatile u32 dect; //减速点
volatile u32 timerload; //保存计算延时值
volatile float timer; //计算曲线中间变量
volatile u16* backtemp; //剩余步数
}sMotor;
sMotor MotorY;
sMotor MotorZ;
sMotor MotorA;
MotorY.backtemp = (u16*)(&IIC_DMA_TxBuf);
MotorZ.backtemp = (u16*)(&IIC_DMA_TxBuf);
MotorA.backtemp = (u16*)(&IIC_DMA_TxBuf);
//使用原MotorP.backtemp成员变量时,改为 (* MotorY.backtemp)
*/
void IIC_GET_ADDRESS()
{
//使能GPIO时钟
//配置GPIO为输入
//读IO,得到硬件IIC地址
IIC_ADDRESS = 0x36; //
}
void IIC_DMA_INIT()
{
IIC_GET_ADDRESS();
RCC->AHB1ENR |= RCC_AHB1RSTR_DMA1RST; //使能DMA1时钟
//IIC DMA 从机接收 (主机写)
DMA1_Stream0->CR &= ~DMA_SxCR_EN; //除能DMA1_Stream0
while(DMA1_Stream0->CR & DMA_SxCR_EN);//确保DMA可以被设置
DMA1->LIFCR |= (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0);//传送前清空DMA1_Stream0所有中断标志
DMA1_Stream0->PAR = (uint32_t)&I2C1->DR;//设置外设地址I2C1->DR地址
DMA1_Stream0->M0AR = (uint32_t)IIC_DMA_RxBuf; //设置内存地址
DMA1_Stream0->NDTR = IICRx_COUNTER; //设置dma传输数据的数量
DMA1_Stream0->CR |= (DMA_SxCR_CHSEL_0 | DMA_SxCR_PL_0 | DMA_SxCR_MINC | DMA_SxCR_CIRC); //设置通道号1,优先级中级,传输方向外设到内存(0不用设),内存递增
DMA1_Stream0->CR |= DMA_SxCR_EN; //开启DMA
//IIC DMA 从机发送(主机读)
DMA1_Stream6->CR &= ~DMA_SxCR_EN; //除能DMA1_Stream6
while(DMA1_Stream6->CR & DMA_SxCR_EN);//确保DMA可以被设置
DMA1->HIFCR |= (DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5);;//传送前清空DMA1_Stream6所有中断标志
DMA1_Stream6->PAR = (uint32_t)&I2C1->DR;//设置外设地址I2C1->DR地址
DMA1_Stream6->M0AR = (uint32_t)IIC_DMA_TxBuf; //设置内存地址
DMA1_Stream6->NDTR = IICTx_COUNTER; //设置dma传输数据的数量
DMA1_Stream6->CR |= ( DMA_SxCR_CHSEL_0 | DMA_SxCR_PL_0 | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_CIRC);//设置通道号1,优先级中级,传输方向内存到外设,内存递增
DMA1_Stream6->CR |= DMA_SxCR_EN;
RCC->AHB1ENR |= RCC_AHB1RSTR_GPIOBRST; //使能GPIOB时钟
GPIOB->AFR &= ~0xFF000000; //设置PB6 7复用IIC模式
GPIOB->AFR |= 0x44000000; //设置PB6 7复用IIC模式
GPIOB->MODER &= ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7); //设置PB6、7为复用模式
GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);
GPIOB->OTYPER |= (GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);//设置PB6、7为开漏输出
GPIOB->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7); //设置PB6、7速度50M
GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6_1 | GPIO_OSPEEDER_OSPEEDR7_1);//设置PB6、7速度50M
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7); //设置PB6 7 上拉
GPIOB->PUPDR |= (GPIO_PUPDR_PUPDR6_0 | GPIO_PUPDR_PUPDR7_0); //设置PB6 7 上拉
RCC->APB1ENR |= RCC_APB1RSTR_I2C1RST; //开启IIC1时钟
I2C1->CR1 |= (I2C_CR1_PE | I2C_CR1_ACK);//启用IIC2模块,并设置应答位
I2C1->CR1 &= ~I2C_CR1_SMBUS; //设置为IIC模式
I2C1->OAR1 &= ~I2C_OAR1_ADDMODE; //设置为7位地址模式
I2C1->OAR1 |= 0x4000; //手册上说改为需要由软件置1
I2C1->OAR1 |= IIC_ADDRESS; //设置地址
//I2C1->OAR2 = (IIC_ADDRESS_2 | 0x01); //设置地址并启用双地址
I2C1->CR2 |= (I2C_CR2_DMAEN);
I2C1->CR1 |= I2C_CR1_NOSTRETCH;
} 谢谢分享谢谢分享谢谢分享 好好,谢谢,看看
页:
[1]
2