tongyh75 发表于 2018-11-26 08:55:12

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;
}

星空下石头 发表于 2018-11-26 08:57:35

whywhyq1w2e3 发表于 2018-11-26 09:22:21

sj820224 发表于 2018-11-26 09:28:24

fxliuqq 发表于 2018-11-26 10:15:15

谢谢分享谢谢分享谢谢分享

clnlover 发表于 2018-11-26 12:14:47

mj8abcd 发表于 2018-11-26 17:16:43

xia20802 发表于 2018-11-29 07:05:42

xia20802 发表于 2018-12-2 15:37:30

13145915150 发表于 2018-12-3 12:58:21

好好,谢谢,看看
页: [1] 2
查看完整版本: STM32F4XX的I2C下的DMA控制代码