1.STM32硬件IIC一直被大家说存在问题,实际测试发现确实是有这种情况,借助网上很多人的经验,终于把硬件IIC写完了。
2.使用DMA时,发现发送数据(写寄存器)时序和实际不符,比如发送4字节数据时,如果DMA缓冲区单字节长度配置为4,则实际时序发现只有三个,需要将DMA缓冲区单字节长度配置为5,才可以正常使用
3.当然,如果使用STM32的HAL库,这些问题其实都可以避免,因为底层ST已经做了超时及错误的处理。
4.使用的IIC为自定义的格式,
写寄存器操作为:
START+ACK(从机的ACK信号)+IIC设备地址+(从机的ACK信号)+START+ACK(从机的ACK信号)+IIC写寄存器地址+ACK(从机的ACK信号)+IIC写数据(4Byte,每个数据后都有ACK)+STOP
读寄存器操作为:
START+ACK(从机的ACK信号)+IIC设备地址+(从机的ACK信号)+START+ACK(从机的ACK信号)+IIC读寄存器地址+ACK(从机的ACK信号)+IIC读数据(4Byte,前n个数据后都有(主机发送的)ACK,最后1byte数据后如果发ACK,表示还有数据要读,如果最后1byte数据后为NACK,后面紧接着就是停止位)+STOP
硬件IIC使用DMA还是不使用DMA,通过宏定义选择,代码如下:
#ifndef _hardiic_h
#define _hardiic_h
#ifdef __cplusplus
extern "C"{
#endif
#include "sys.h"
#define AT24Cxx_PageSize 8 //存储器块大小
#define I2C_TIME ((u32)65535)
#define DMA_USER 1
#define HARD_IIC_USER 0 //是否使用硬件IIC而不使用DMA,现在不使用DMA正常,使用DMA连续读还是有问题
#define IIC_DMA_BUFF_LEN 4
#define IIC_READ_DATA_REG_LEN 16
#define IIC_REV_BUFF_LEN IIC_READ_DATA_REG_LEN
/**********全局宏定义,结构体,枚举等***********/
extern u8 IIC_DmaRevBuff[IIC_REV_BUFF_LEN];
extern u8 IIC_RevBuff[IIC_REV_BUFF_LEN];
extern u8 IIC_SendBuff[IIC_REV_BUFF_LEN];
extern u8 g_ackFlag;
extern u8 g_ackErrorFlag;
void Hard_IIC_Init(u8 SlaveAdd);
void IIC_DmaInit(u8 SlaveAdd);
void IIC_TxDmaConfig(u8 *pbuff, u8 len);
void IIC_RxDmaConfig(u8 *pbuff, u16 len, u8 it_mode);
void I2C_DMA_Read(u8 SlaveAddr,u8 ReadAddr, u8 *err);
u32 I2C_DMA_ReadReg(u8 ReadAddr, u8 *err);
void I2C_DMA_ReadDataAddrReg(void);
void I2C_DMA_Write(u8 SlaveAddr, u8 WriteAddr,u32 DataToWrite, u8 *err);
void I2C_DMA_WriteReg(u8 WriteAddr,u32 DataToWrite, u8 *err);
void Hard_IICWaiteStandby(uint8_t SlaveAdd);
void IIC_DataRegToUart(void);
//void IIC_HardWriteOneWord(u8 SlaveAdd, u8 WriteAdd, u32 write_data, u8 * err);
//u32 IIC_HardReadOneWord(uint8_t SlaveAdd, u8 ReadAdd, u8 * err);
//void IIC_HardReadNWord(void);
/**
****************************** Support C++ **********************************
**/
#ifdef __cplusplus
}
#endif
/**
*****************************************************************************
**/
#endif /* end hardiic.h */
#include "hardiic.h"
#include "iic_link.h"
#include "uart_cmd_handle.h"
#include "delay.h"
#include "uartfifo.h"
//#include "DMA.h"
u8 IIC_DmaRevBuff[IIC_REV_BUFF_LEN] = {0x00};
u8 IIC_RevBuff[IIC_REV_BUFF_LEN] = {0x00};
u8 IIC_SendBuff[IIC_REV_BUFF_LEN] = {0x00};
u8 g_ackFlag = 0;
u8 g_ackErrorFlag = 0;
u8 g_continuFlag = 0;
u8 g_readDataEvent = 0;
//硬件IIC初始化
void Hard_IIC_Init(u8 SlaveAdd)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
I2C_DeInit(I2C1);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//管脚复用
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
//配置IIC参数
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = SlaveAdd; //从设备地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000; //SCL最大400KHz
I2C_Cmd(I2C1, ENABLE);
// I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_ERR , ENABLE);
I2C_Init(I2C1, &I2C_InitStructure);
I2C_AcknowledgeConfig(I2C1, ENABLE);
//禁止时钟延长
I2C1->CR1 |= 0x80;
// //允许时钟延长
// I2C1->CR1 &= 0x7F;
}
硬件IIC DMA初始化
void IIC_DmaInit(u8 SlaveAdd)
{
NVIC_InitTypeDef NVIC_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
Hard_IIC_Init(SlaveAdd);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Stream0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Stream6_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_FEIF6 | DMA_FLAG_DMEIF6 | DMA_FLAG_TEIF6 |
// DMA_FLAG_HTIF6 | DMA_FLAG_TCIF6);
// DMA_Cmd(DMA1_Stream6, DISABLE);
// DMA_DeInit(DMA1_Stream6);
// IIC_TxDmaConfig(IIC_SendBuff, IIC_BUFF_LEN); //IIC TX DMA初始化
// DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_FEIF0 | DMA_FLAG_DMEIF0 | DMA_FLAG_TEIF0 |
// DMA_FLAG_HTIF0 | DMA_FLAG_TCIF0);
// DMA_Cmd(DMA1_Stream0, DISABLE);
// DMA_DeInit(DMA1_Stream0);
// IIC_RxDmaConfig(IIC_RevBuff, IIC_BUFF_LEN); //IIC RX DMA初始化
// DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, ENABLE);
// DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
// I2C_DMACmd(I2C1, ENABLE);
}
void Hard_IICWaiteStandby(uint8_t SlaveAdd)
{
u16 tmp = 0;
I2C1->SR1 &= 0x0000; //清除状态寄存器1
do
{
I2C_GenerateSTART(I2C1, ENABLE); //产生起始信号
tmp = I2C1->SR1; //读取SR1寄存器,然后写入数据寄存器操作来清除SB位,EV5
I2C_Send7bitAddress(I2C1, SlaveAdd, I2C_Direction_Transmitter); //发送从设备地址
} while ((I2C1->SR1 & 0x0002) == 0x0000); //当ADDR = 1时,表明应答了,跳出循环
I2C_ClearFlag(I2C1, I2C_FLAG_AF); //清除应答失败标志位
I2C_GenerateSTOP(I2C1, ENABLE); //发送停止信号
}
#if HARD_IIC_USER
//写一个寄存器
void I2C_DMA_WriteReg(u8 WriteAdd, u32 write_data, u8 * err)
{
u16 sta = 0;
u16 temp = 0;
u8 NumToWrite = 4;
u8 write_value = 0;
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) //等待IIC
{
temp++;
if (temp > 800)
{
*err |= 1<<0;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_GenerateSTART(I2C1, ENABLE); //产生起始信号
temp = 0;
//EV5
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
temp++;
if (temp > 800)
{
*err |= 1<<1;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_ADDR, I2C_Direction_Transmitter); //发送设备地址
temp = 0;
//EV6
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
temp++;
if (temp > 1000)
{
*err |= 1<<2;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
//读取SR2状态寄存器
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_SendData(I2C1, WriteAdd); //发送存储地址
temp = 0;
//EV8
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
temp++;
if (temp > 800)
{
*err |= 1<<3;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_GenerateSTART(I2C1, ENABLE); //产生起始信号
temp = 0;
//EV5
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
temp++;
if (temp > 800)
{
*err |= 1<<1;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_ADDR, I2C_Direction_Transmitter); //发送设备地址
temp = 0;
//EV6
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
temp++;
if (temp > 1000)
{
*err |= 1<<2;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
//读取SR2状态寄存器
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
//循环发送数据
while (NumToWrite)
{
NumToWrite--;
write_value = (u8)(write_data>>(NumToWrite*8));
I2C_SendData(I2C1, write_value); //发送数据
temp = 0;
//EV8_2
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
temp++;
if (temp > 800)
{
*err |= 1<<4;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
}
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
Hard_IICWaiteStandby(IIC_LINK_ADDR); //等待完成操作
}
u32 I2C_DMA_ReadReg(u8 ReadAdd, u8 * err)
{
u16 i = 0;
u16 sta = 0;
u8 NumToRead = 4;
u8 pbuff[4] = {0x00};
u32 ret = 0;
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) //等待IIC
{
i++;
if (i > 800)
{
*err |= 1<<0;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return 0;
}
}
I2C_GenerateSTART(I2C1, ENABLE); //发送起始信号
i = 0;
//EV5
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if (i > 800)
{
*err |= 1<<1;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return 0;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_ADDR, I2C_Direction_Transmitter); //发送设备地址
i = 0;
//EV6
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
i++;
if (i > 800)
{
*err |= 1<<2;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return 0;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_SendData(I2C1, ReadAdd); //发送存储地址
i = 0;
//EV8
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
i++;
if (i > 2000)
{
*err |= 1<<3;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return 0;
}
}
I2C_GenerateSTART(I2C1, ENABLE); //重启信号
i = 0;
//EV5
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if (i > 800)
{
*err |= 1<<4;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return 0;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_ADDR, I2C_Direction_Receiver); //读取命令
i = 0;
//EV6
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
i++;
if (i > 800)
{
*err |= 1<<5;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return 0;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
//批量接收数据
while (NumToRead)
{
if (NumToRead == 1) //最后一个数据了,不发送应答信号
{
I2C_AcknowledgeConfig(I2C1, DISABLE); //发送NACK
I2C_GenerateSTOP(I2C1, ENABLE);
}
//判断RxNE是否为1,EV7
if (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
{
NumToRead--;
pbuff[3-NumToRead] = I2C_ReceiveData(I2C1);
}
}
I2C_AcknowledgeConfig(I2C1, ENABLE);
ret = (pbuff[0]<<24) + (pbuff[1]<<16) + (pbuff[2]<<8) + pbuff[3];
return ret;
}
void I2C_DMA_ReadDataAddrReg(void)
{
u16 i = 0;
u8 sta;
u8 NumToRead = 4;
u8 pbuffer[IIC_READ_DATA_REG_LEN] = {0x00};
u8 error = 0;
Hard_IIC_Init(IIC_LINK_ADDR0);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) //等待IIC
{
i++;
if (i > 800)
{
error |= 1<<0;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_GenerateSTART(I2C1, ENABLE); //发送起始信号
i = 0;
//EV5
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if (i > 800)
{
error |= 1<<1;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_ADDR, I2C_Direction_Transmitter); //发送设备地址
i = 0;
//EV6
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
i++;
if (i > 800)
{
error |= 1<<2;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_SendData(I2C1, 0xff); //发送存储地址
i = 0;
//EV8
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
i++;
if (i > 2000)
{
error |= 1<<3;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_GenerateSTART(I2C1, ENABLE); //重启信号
i = 0;
//EV5
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if (i > 800)
{
error |= 1<<4;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_ADDR, I2C_Direction_Receiver); //读取命令
i = 0;
//EV6
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
i++;
if (i > 800)
{
error |= 1<<5;
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
// DealDataFromUart1();
error = 0;
i=0;
NumToRead = IIC_READ_DATA_REG_LEN;
//批量接收数据
while (NumToRead)
{
if(NumToRead == 1) //最后一个数据了,不发送应答信号
{
I2C_AcknowledgeConfig(I2C1, DISABLE); //发送NACK
I2C_GenerateSTOP(I2C1, ENABLE);
}
//判断RxNE是否为1,EV7
if (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
{
NumToRead--;
pbuffer[i++] = I2C_ReceiveData(I2C1);
}
}
for(i=0;i<IIC_READ_DATA_REG_LEN;i++) //数据放入缓冲区
{
IICinfifo_DataIn(pbuffer[i]);
}
IICinfifo_DataIn(error);
g_readDataEvent = 1;
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
#else
void IIC_TxDmaConfig(u8 *pbuff, u8 len)
{
DMA_InitTypeDef DMA_InitStruct;
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// IIC_DmaInit(IIC_LINK_ADDR0);
DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_FEIF6 | DMA_FLAG_DMEIF6 | DMA_FLAG_TEIF6 |
DMA_FLAG_HTIF6 | DMA_FLAG_TCIF6);
DMA_Cmd(DMA1_Stream6, DISABLE);
// DMA_DeInit(DMA1_Stream6);
while (DMA_GetCmdStatus(DMA1_Stream6) != DISABLE);
DMA_InitStruct.DMA_Channel = DMA_Channel_1;
DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)&I2C1->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (u32)&pbuff[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_BufferSize = len+1;//IIC_BUFF_LEN;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream6, &DMA_InitStruct);
DMA_ITConfig(DMA1_Stream6, DMA_IT_TC|DMA_IT_TE, ENABLE);
I2C_DMACmd(I2C1, ENABLE);
while (DMA_GetCmdStatus(DMA1_Stream6) != DISABLE);
DMA_Cmd(DMA1_Stream6, ENABLE);
}
void IIC_RxDmaConfig(u8 *pbuff, u16 len, u8 it_mode)
{
DMA_InitTypeDef DMA_InitStruct;
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// IIC_DmaInit(IIC_LINK_ADDR0);
DMA_Cmd(DMA1_Stream0, DISABLE);
while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE);
// DMA_DeInit(DMA1_Stream0);
DMA_InitStruct.DMA_Channel = DMA_Channel_1;
DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)&I2C1->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (u32)&pbuff[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_BufferSize = len;//IIC_BUFF_LEN;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream0, &DMA_InitStruct);
DMA_ITConfig(DMA1_Stream0, DMA_IT_TC|DMA_IT_TE, ENABLE);
I2C_DMACmd(I2C1, ENABLE);
while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE);
I2C_DMALastTransferCmd(I2C1, ENABLE);
DMA_Cmd(DMA1_Stream0, ENABLE);
}
vu32 I2C_TimeCnt = I2C_TIME;
void I2C_DMA_Read(u8 SlaveAddr,u8 ReadAddr, u8 *err)
{
u16 sta = 0;
*err = 0;
g_ackErrorFlag = 0;
g_ackFlag = 0;
g_continuFlag = 0;
IIC_DmaInit(IIC_LINK_ADDR0);
I2C_TimeCnt = I2C_TIME;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<0);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_GenerateSTART(I2C1, ENABLE);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<1);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_Send7bitAddress(I2C1, SlaveAddr, I2C_Direction_Transmitter);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //I2C_EVENT_MASTER_BYTE_TRANSMITTING
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<2);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_SendData(I2C1, ReadAddr);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<3);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_GenerateSTART(I2C1, ENABLE);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<4);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_Send7bitAddress(I2C1, SlaveAddr, I2C_Direction_Receiver);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<5);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
IIC_RxDmaConfig(IIC_DmaRevBuff, IIC_DMA_BUFF_LEN, 0); //IIC RX DMA初始化
}
u32 I2C_DMA_ReadReg(u8 ReadAddr, u8 *err)
{
u32 temp = 0;
I2C_DMA_Read(IIC_LINK_WRITE_MODE, ReadAddr, err);
I2C_TimeCnt = I2C_TIME;
while(g_ackFlag==0)
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<6);
break;
}
}
*err |= (g_ackErrorFlag<<7);
temp = (IIC_DmaRevBuff[0]<<24) + (IIC_DmaRevBuff[1]<<16) + (IIC_DmaRevBuff[2]<<8) + IIC_DmaRevBuff[3];
return temp;
}
//连续读数据
void I2C_DMA_ReadDataAddrReg(void)
{
u16 sta = 0;
g_ackErrorFlag = 0;
g_ackFlag = 0;
IIC_DmaInit(IIC_LINK_ADDR0);
I2C_TimeCnt = I2C_TIME;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag |= (0x01<<0);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_GenerateSTART(I2C1, ENABLE);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag |= (0x01<<1);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_WRITE_MODE, I2C_Direction_Transmitter);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //I2C_EVENT_MASTER_BYTE_TRANSMITTING
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag |= (0x01<<2);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_SendData(I2C1, 0xff);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag |= (0x01<<3);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_GenerateSTART(I2C1, ENABLE);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag |= (0x01<<4);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
I2C_Send7bitAddress(I2C1, IIC_LINK_WRITE_MODE, I2C_Direction_Receiver);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag |= (0x01<<5);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return ;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
g_continuFlag = 1; //连续读取标志
g_readDataEvent = 0;
IIC_RxDmaConfig(IIC_DmaRevBuff, IIC_READ_DATA_REG_LEN,0); //IIC RX DMA初始化
I2C_TimeCnt = I2C_TIME;
while(g_ackFlag==0)
{
if((I2C_TimeCnt--) == 0)
{
break;
}
}
// delay_ms(10);
// goto HARD_IIC_LOOP2;
// DMA_Cmd(DMA1_Stream0, DISABLE); //关闭DMA传输
// while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE){} //确保DMA可以被设置
// DMA_MemoryTargetConfig(DMA1_Stream0, (u32)&IIC_RevBuff[0], DMA_Memory_0);
// DMA_SetCurrDataCounter(DMA1_Stream0, IIC_DMA_BUFF_LEN-1); //数据传输量
// DMA_Cmd(DMA1_Stream0, ENABLE); //开启DMA传输
}
void I2C_DMA_Write(u8 SlaveAddr, u8 WriteAddr,u32 DataToWrite, u8 *err)
{
u16 sta;
*err = 0;
g_ackErrorFlag = 0;
g_ackFlag = 0;
IIC_DmaInit(IIC_LINK_ADDR0);
I2C_TimeCnt = I2C_TIME;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<0);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_GenerateSTART(I2C1, ENABLE);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<1);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_Send7bitAddress(I2C1, SlaveAddr, I2C_Direction_Transmitter);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //I2C_EVENT_MASTER_BYTE_TRANSMITTING
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<2);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_SendData(I2C1, WriteAddr);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<3);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_GenerateSTART(I2C1, ENABLE);
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<4);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
I2C_Send7bitAddress(I2C1, SlaveAddr, I2C_Direction_Transmitter);
sta = I2C1->SR2; //软件读取SR1寄存器后,对SR2寄存器的读操作将清除ADDR位,不可少!!!!!!!!!
I2C_TimeCnt = I2C_TIME;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<5);
I2C_GenerateSTOP(I2C1, ENABLE); //产生停止信号
return;
}
}
IIC_SendBuff[0] = (DataToWrite>>24)&0xff;
IIC_SendBuff[1] = (DataToWrite>>16)&0xff;
IIC_SendBuff[2] = (DataToWrite>>8)&0xff;
IIC_SendBuff[3] = (DataToWrite>>0)&0xff;
IIC_TxDmaConfig(IIC_SendBuff, IIC_DMA_BUFF_LEN); //IIC TX DMA初始化
}
void I2C_DMA_WriteReg(u8 WriteAddr,u32 DataToWrite, u8 *err)
{
I2C_DMA_Write(IIC_LINK_WRITE_MODE, WriteAddr, DataToWrite, err);
I2C_TimeCnt = I2C_TIME;
while(g_ackFlag==0)
{
if((I2C_TimeCnt--) == 0)
{
*err |= (0x01<<4);
break;
}
}
*err |= (g_ackErrorFlag<<5);
// Hard_IICWaiteStandby(IIC_LINK_ADDR); //等待完成操作
return;
}
void DMA1_Stream6_IRQHandler( void )
{
if(DMA_GetFlagStatus(DMA1_Stream6, DMA_FLAG_TCIF6) != RESET) //传输完成中断
{
DMA_Cmd(DMA1_Stream6, DISABLE);
DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6);
I2C_TimeCnt = I2C_TIME;
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF))
{
if((I2C_TimeCnt--) == 0)
{
g_ackErrorFlag = 1;
}
break;
}
I2C_GenerateSTOP(I2C1, ENABLE);
g_ackErrorFlag = 0;
g_ackFlag = 1;
}
else if(DMA_GetITStatus(DMA1_Stream6,DMA_IT_TEIF6) != RESET) //传输失败中断
{
DMA_Cmd(DMA1_Stream6, DISABLE);
DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_TEIF6);
I2C_GenerateSTOP(I2C1, ENABLE);
g_ackErrorFlag = 1;
g_ackFlag = 1;
}
}
void DMA1_Stream0_IRQHandler( void )
{
u8 i=0;
if(DMA_GetFlagStatus(DMA1_Stream0, DMA_FLAG_TCIF0) != RESET)
{
DMA_Cmd(DMA1_Stream0, DISABLE);
DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_TCIF0);
I2C_GenerateSTOP(I2C1, ENABLE);
if(g_continuFlag == 1) //连续读数据
{
for(i=0; i<IIC_READ_DATA_REG_LEN; i++)
{
IICinfifo_DataIn(IIC_DmaRevBuff[i]);
IIC_DmaRevBuff[i] = 0;
}
IICinfifo_DataIn(g_ackErrorFlag);
}
g_ackErrorFlag = 0;
g_ackFlag = 1;
g_readDataEvent = 1;
}
// else if(DMA_GetITStatus(DMA1_Stream0,DMA_IT_HTIF0) != RESET) //半传输完成中断
// {
// DMA_Cmd(DMA1_Stream0, DISABLE);
// DMA_ClearITPendingBit(DMA1_Stream0,DMA_IT_HTIF0);
// g_ackErrorFlag = 0;
// g_ackFlag = 1;
// }
else if(DMA_GetITStatus(DMA1_Stream0,DMA_IT_TEIF0) != RESET) //传输失败中断
{
DMA_Cmd(DMA1_Stream0, DISABLE);
DMA_ClearITPendingBit(DMA1_Stream0,DMA_IT_TEIF0);
I2C_GenerateSTOP(I2C1, ENABLE);
g_ackErrorFlag = 1;
g_ackFlag = 1;
}
}
#endif
void IIC_DataRegToUart(void)
{
u8 i, j;
u8 pbuffer[IIC_READ_DATA_REG_LEN+10] = {0x00};
while(g_readDataEvent!=1){}
while(IICinfifo_HaveData() != 0)
{
i=0;
pbuffer[i++] = 0x30;
pbuffer[i++] = 0xff;
for(j=0;j<(IIC_READ_DATA_REG_LEN+1);j++)
{
pbuffer[i++] = IICinfifo_DataOut();
}
UART1_SendCmdData(pbuffer, i);
delay_ms(10);
}
}
int main(void)
{
u8 error=0;
u32 jiCunQi_data = 0;
IIC_DmaInit(IIC_LINK_ADDR0);
//寄存器0x02,写0x00000001
I2C_DMA_WriteReg(0x02, 0x00000001, &error);
//读0x02寄存器
jiCunQi_data = I2C_DMA_ReadReg(0x02, &error);
while(1);
}