STM32模拟IIC 代码
头文件代码:
simulate_i2c.h
#include "stm32f4xx.h"
#include "main.h"
//切换控制IIC时用
extern GPIO_TypeDef* IIC_SCL_Port;
extern uint16_t IIC_SCL_Pin;
extern GPIO_TypeDef* IIC_SDA_Port;
extern uint16_t IIC_SDA_Pin;
//IIC引脚切换
void setISL21400andTMP75IICPin();
void setAD5316IICPin();
#define useSimulateIIC
#ifdef useSimulateIIC
#define SDA_IN()
#define SDA_OUT()
#define SCL_1() HAL_GPIO_WritePin(IIC_PA_SCL_GPIO_Port, IIC_PA_SCL_Pin, GPIO_PIN_SET)
#define SCL_0() HAL_GPIO_WritePin(IIC_PA_SCL_GPIO_Port, IIC_PA_SCL_Pin, GPIO_PIN_RESET)
#define SDA_1() HAL_GPIO_WritePin(IIC_PA_SDA_GPIO_Port, IIC_PA_SDA_Pin, GPIO_PIN_SET)
#define SDA_0() HAL_GPIO_WritePin(IIC_PA_SDA_GPIO_Port, IIC_PA_SDA_Pin, GPIO_PIN_RESET)
#define SDA_read() HAL_GPIO_ReadPin(IIC_PA_SDA_GPIO_Port, IIC_PA_SDA_Pin)
void I2cStart(void); //起始信号
void I2cStop(void); //终止信号
void I2cAck(void); //发送应答信号
void I2cNAck(void); //发送非应答信号
uint8_t I2cWaitAck(void); //等待应答信号
uint8_t I2cSendByte(uint8_t Byte); //IIC发送一个字节
uint8_t I2cReadByte(void); //IIC读取一个字节
#endif
uint8_t CheckDeviceI2C(uint8_t DeviceAddress); //检测应答
//往器件的一个地址写入一个数据(器件地址,寄存器地址,数据)
uint8_t WriteI2C(uint8_t SlaveAddress,uint8_t RegistAddress,uint8_t RegistData);
//读取器件的一个地址的一个数据(器件地址,寄存器地址)
uint8_t ReadI2C(uint8_t SlaveAddress,uint8_t RegistAddress);
//往器件的一个地址写入一个数据(器件地址,寄存器地址,数据长度,数据数组)
uint8_t setI2C(uint8_t DeviceAddress,uint8_t RegistAddress,uint8_t DateLength,uint8_t* RegistData);
//读取器件的一个地址的一个数据(器件地址,寄存器地址,数据长度,数据数组)
uint8_t getI2C(uint8_t DeviceAddress,uint8_t RegistAddress,uint8_t DateLength,uint8_t* RegistData);
simulate_i2c.c
#include <TimTask.h>
#include "simulate_i2c.h"
#include "main.h"
#include "cmsis_os.h"
#include "globalData.h"
GPIO_TypeDef* IIC_SCL_Port;
uint16_t IIC_SCL_Pin;
GPIO_TypeDef* IIC_SDA_Port;
uint16_t IIC_SDA_Pin;
#ifdef useSimulateIIC
//延时STM32F407ZE -168M,(STM32CubeIDE 优化等级none O0,不然会优化掉无延时)
static void delay_us(uint8_t us){
uint32_t n;
switch(us){ //调用函数花的时间约1.21us
case 1:
for(n=0x07; n>0;n--); //这里调试得的加上调用函数延时1us-1.05us 0x07
break;
case 2:
for(n=0x15; n>0;n--); //这里调试得的加上调用函数延时2us-2.05us 0x15
break;
case 3:
for(n=0x23; n>0;n--); //这里调试得的加上调用函数延时3.0us 0x23
break;
case 4:
for(n=0x31; n>0;n--); //这里调试得的加上调用函数延时4us-4.05us 0x31
break;
case 5:
for(n=0x3F; n>0;n--); //这里调试得的加上调用函数延时5us-5.05us 0x3F
break;
}
}
//起始信号
void I2cStart(void){
SDA_1();
SCL_1();
delay_us(4);
SDA_0(); //SCL高,SDA下降,起始信号
delay_us(4);
SCL_0();
}
//终止信号
void I2cStop(void){
SDA_0();
SCL_1();
delay_us(4);
SDA_1(); //SCL高,SDA上升,终止信号
delay_us(4);
}
//产生ACK应答
void I2cAck(void){
SDA_0();
SCL_0();
delay_us(1);
SCL_1();
delay_us(1);
SCL_0();
delay_us(1);
SDA_1(); //CPU释放SDA总线
}
//产生非应答
void I2cNAck(void){
SDA_1();
SCL_0();
delay_us(1);
SCL_1();
delay_us(1);
SCL_0();
delay_us(1);
SDA_1(); //CPU释放SDA总线
}
//等待应答
uint8_t I2cWaitAck(void){
uint16_t n=500; //错误等待延时
SDA_IN(); //改引脚为输入模式
while(SDA_read()){ //等待一定时间的应答,应答超时终止i2c
n--;
if(n==0){
I2cStop(); ///未应答。结束
return 1;
}
}
SCL_0();
SDA_OUT(); //改引脚为输出模式
return 0;
}
//通过I2C发送一个字节,返回0发送成功,1未应答
uint8_t I2cSendByte(uint8_t Byte){
uint8_t i,ack;
for(i=0;i<8;i++){
if(Byte>>7){
SDA_1();
}else{
SDA_0();
}
Byte<<= 1;
delay_us(2);
SCL_1(); //发送有效电平
delay_us(2);
SCL_0();
delay_us(2);
}
SDA_1(); //释放SDA总线
delay_us(1);
SCL_1();
delay_us(1);
ack=I2cWaitAck();
return ack;
}
//使用I2c读取一个字节
uint8_t I2cReadByte(void){
uint8_t i,value=0;
SDA_IN(); //改引脚为输入模式
for(i=0;i<8;i++ ){
SCL_0();
delay_us(2);
SCL_1();
value<<=1;
if(SDA_read()){
value++;
}
delay_us(1);
}
SCL_0();
SDA_OUT(); //改引脚为输出模式
return value;
}
//通过应答判断从机是否正常,为未应答返回1,应答返回0
uint8_t CheckDeviceI2C(uint8_t DeviceAddress){
uint8_t ack;
I2cStop(); //给一个停止信号, 复位I2C总线上的所有设备到待机模式
I2cStart(); //起始信号
ack=I2cSendByte((DeviceAddress<<1)|0); //发送设备地址+读写控制bit(0=wite,1=read)
I2cStop();
return ack;
}
//往器件的一个地址写入一个数据(器件地址,寄存器地址,数据)
uint8_t WriteI2C(uint8_t SlaveAddress,uint8_t RegistAddress,uint8_t RegistData){
I2cStart(); //起始信号
if(I2cSendByte((SlaveAddress<<1)|0)){ //发送设备地址+写信号
I2cStop();
return 1;
}
I2cSendByte(RegistAddress); //内部寄存器地址
if(I2cSendByte(RegistData)){ //内部寄存器数据
I2cStop();
return 1;
}
I2cStop(); //发送停止信号
return 0;
}
//读取器件的一个地址的一个数据(器件地址,寄存器地址)
uint8_t ReadI2C(uint8_t SlaveAddress,uint8_t RegistAddress){
uint8_t REG_data;
I2cStart(); //起始信号
if(I2cSendByte((SlaveAddress<<1)|0)){ //发送设备地址+写信号
I2cStop();
return 1;
}
I2cSendByte(RegistAddress); //内部寄存器地址
I2cStart();
if(I2cSendByte((SlaveAddress<<1)|1)){ //发送器件地址+读信号
I2cStop();
return 1;
}
REG_data=I2cReadByte(); //读取数据
I2cNAck(); //不应答
I2cStop(); //发送停止信号
return REG_data;
}
//往器件的一个地址写数据(器件地址,寄存器地址,数据长度,数据数组指针)
uint8_t setI2C(uint8_t DeviceAddress,uint8_t RegistAddress,uint8_t DateLength,uint8_t* RegistData){
uint8_t i;
I2cStart(); //起始信号
if(I2cSendByte((DeviceAddress<<1)|0)){ //发送设备地址+写信号
I2cStop();
return 1;
}
I2cSendByte(RegistAddress); //内部寄存器地址
for(i=0;i<DateLength;i++){
if(I2cSendByte(RegistData[i])){ //连续数据数据
I2cStop();
return 1;
}
}
I2cStop(); //发送停止信号
return 0;
}
//读取器件的一个地址的数据(器件地址,寄存器地址,数据长度,数据数组指针)
uint8_t getI2C(uint8_t DeviceAddress,uint8_t RegistAddress,uint8_t DateLength,uint8_t* RegistData){
I2cStart(); //起始信号
if(I2cSendByte((DeviceAddress<<1)|0)){ //发送设备地址+写信号
I2cStop();
return 1;
}
I2cSendByte(RegistAddress); //内部寄存器地址
I2cStart(); //起始信号
if(I2cSendByte((DeviceAddress<<1)|1)){ //发送设备地址+读信号
I2cStop();
return 1;
}
while(1){ //连续读数据
if(DateLength==1){
*RegistData=I2cReadByte();
I2cNAck();
break;
}else{
*RegistData=I2cReadByte();
I2cAck();
DateLength--;
RegistData++;
}
}
I2cStop(); //发送停止信号
return 0;
}
#else
/******* Blocking mode: Polling
* i2c里面: __HAL_RCC_I2C1_CLK_ENABLE();
*
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);
*/
uint8_t CheckDeviceI2C(uint8_t DeviceAddress){
//检查设备是否淮备好 地址 检查次数 超时时间
return HAL_I2C_IsDeviceReady(&hi2c1, DeviceAddress, 1, 100);
}
//往器件的一个地址写入一个数据(器件地址,寄存器地址,数据)
uint8_t WriteI2C(uint8_t SlaveAddress,uint8_t RegistAddress,uint8_t RegistData){
SlaveAddress=(SlaveAddress<<1);
return HAL_I2C_Mem_Write(&hi2c1,SlaveAddress,RegistAddress,I2C_MEMADD_SIZE_8BIT,&RegistData,1,100);
}
//读取器件的一个地址的一个数据(器件地址,寄存器地址)
uint8_t ReadI2C(uint8_t SlaveAddress,uint8_t RegistAddress){
uint8_t readData;
SlaveAddress=(SlaveAddress<<1)+1;
HAL_I2C_Mem_Read(&hi2c1,SlaveAddress,RegistAddress,I2C_MEMADD_SIZE_8BIT,&readData,1,100);
return readData;
}
//往器件的一个地址写数据(器件地址,寄存器地址,数据长度,数据数组指针)
uint8_t setI2C(uint8_t DeviceAddress,uint8_t RegistAddress,uint8_t DateLength,uint8_t* RegistData){
DeviceAddress=(DeviceAddress<<1);
return HAL_I2C_Mem_Write(&hi2c1,DeviceAddress,RegistAddress,I2C_MEMADD_SIZE_8BIT,RegistData,DateLength,100);
}
//读取器件的一个地址的数据(器件地址,寄存器地址,数据长度,数据数组指针)
uint8_t getI2C(uint8_t DeviceAddress,uint8_t RegistAddress,uint8_t DateLength,uint8_t* RegistData){
DeviceAddress=(DeviceAddress<<1)+1;
return HAL_I2C_Mem_Read(&hi2c1,DeviceAddress,RegistAddress,I2C_MEMADD_SIZE_8BIT,RegistData,DateLength,100);
}
#endif
需要示波器调试simulate_i2c.c的delay函数:
//延时STM32F407ZE -168M,(STM32CubeIDE 优化等级none O0,不然会优化掉无延时)
static void delay_us(uint8_t us){
uint32_t n;
switch(us){ //调用函数花的时间约1.21us
case 1:
for(n=0x07; n>0;n--); //这里调试得的加上调用函数延时1us-1.05us 0x07
break;
case 2:
for(n=0x15; n>0;n--); //这里调试得的加上调用函数延时2us-2.05us 0x15
break;
case 3:
for(n=0x23; n>0;n--); //这里调试得的加上调用函数延时3.0us 0x23
break;
case 4:
for(n=0x31; n>0;n--); //这里调试得的加上调用函数延时4us-4.05us 0x31
break;
case 5:
for(n=0x3F; n>0;n--); //这里调试得的加上调用函数延时5us-5.05us 0x3F
break;
}
}
————————————————
版权声明:本文为CSDN博主「几个叶子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44015616/article/details/153936969
|
|