STM8L152模拟IIC程序

更新时间:2023-03-08 06:25:11 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

STM8L152模拟IIC程序

//初始化IIC接口

void AT24CXX_Init(void) {

IIC_Init(); }

//在AT24CXX指定地址读出一个数据 //ReadAddr:开始读数的地址 //返回值 :读到的数据

u8 AT24CXX_ReadOneByte(u16 ReadAddr) {

u8 temp=0; IIC_Start();

if(EE_TYPE>AT24C16) {

IIC_Send_Byte(0XA0); //发送写命令 IIC_Wait_Ack();

IIC_Send_Byte(ReadAddr>>8);//发送高地址 IIC_Wait_Ack();

}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据

IIC_Wait_Ack();

IIC_Send_Byte(ReadAddr%6); //发送低地址 IIC_Wait_Ack(); IIC_Start();

IIC_Send_Byte(0XA1); //进入接收模式 IIC_Wait_Ack();

temp=IIC_Read_Byte(0);

IIC_Stop();//产生一个停止条件 return temp; }

//在AT24CXX指定地址写入一个数据 //WriteAddr :写入数据的目的地址 //DataToWrite:要写入的数据

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)

{ IIC_Start();

if(EE_TYPE>AT24C16) {

IIC_Send_Byte(0XA0); //发送写命令 IIC_Wait_Ack();

IIC_Send_Byte(WriteAddr>>8);//发送高地址 }else {

IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据 }

IIC_Wait_Ack();

IIC_Send_Byte(WriteAddr%6); //发送低地址

IIC_Wait_Ack(); IIC_Send_Byte(DataToWrite); //发送字节

IIC_Wait_Ack(); IIC_Stop();//产生一个停止条件 delay_us(20000); }

//在AT24CXX里面的指定地址开始写入长度为Len的数据 //该函数用于写入16bit或者32bit的数据. //WriteAddr :开始写入的地址 //DataToWrite:数据数组首地址

//Len :要写入数据的长度2,4

void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len) { u8 t;

for(t=0;t

AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff); } }

//在AT24CXX里面的指定地址开始读出长度为Len的数据 //该函数用于读出16bit或者32bit的数据. //ReadAddr :开始读出的地址 //返回值 :数据

//Len :要读出数据的长度2,4

u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len) { u8 t;

u32 temp=0; for(t=0;t

temp<<=8;

temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1); }

return temp; }

//检查AT24CXX是否正常

//这里用了24XX的最后一个地址(255)来存储标志字. //如果用其他24C系列,这个地址要修改 //返回1:检测失败 //返回0:检测成功

u8 AT24CXX_Check(void) {

u8 temp;

temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX

if(temp==0X55)return 0; else//排除第一次初始化的情况 {

AT24CXX_WriteOneByte(255,0X55);

temp=AT24CXX_ReadOneByte(255); if(temp==0X55)return 0; }

return 1; }

//在AT24CXX里面的指定地址开始读出指定个数的数据 //ReadAddr :开始读出的地址 对24c02为0~255 //pBuffer :数据数组首地址 //NumToRead:要读出数据的个数

void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead) {

while(NumToRead) {

*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++); NumToRead--; } }

//在AT24CXX里面的指定地址开始写入指定个数的数据 //WriteAddr :开始写入的地址 对24c02为0~255 //pBuffer :数据数组首地址 //NumToWrite:要写入数据的个数

void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite) {

while(NumToWrite--) {

AT24CXX_WriteOneByte(WriteAddr,*pBuffer); WriteAddr++; pBuffer++; } } 本篇仍然是模拟IIC,基本思路仍然是STM32的模拟IIC思路。具体内容还是参考STM32使用模拟IIC操作EEPROM。 示例代码如下:

stm8_iic.h文件内容如下: #ifndef _stm8_iic_h_ #define _stm8_iic_h_

#include \

extern unsigned char BQ25890x_write_reg(unsigned char *buffer,unsigned char addr,unsigned char num);

extern unsigned char BQ25890x_read_reg(unsigned char *buffer,unsigned char addr,unsigned char num);

#define IICSPEED 100000

#define BQ25890_I2C_ADDR (0x6A) #endif

stm8_iic.c内容如下:

#define SlaveAddress (BQ25890_I2C_ADDR) #define IIC_SDA_GPIO_Pin GPIO_Pin_0 #define IIC_SCL_GPIO_Pin GPIO_Pin_1 #define IIC_GPIOx GPIOC

void Delay(void) { nop(); nop(); nop(); nop(); nop(); nop(); }

//使用软件模拟IIC //PC0--SDA PC1---SCL //初始化

void BQ25890H_init(void) {

GPIO_Init(IIC_GPIOx, IIC_SDA_GPIO_Pin, GPIO_Mode_Out_PP_High_Fast);

GPIO_Init(IIC_GPIOx, IIC_SCL_GPIO_Pin, GPIO_Mode_Out_PP_High_Fast); }

//读取数据

unsigned char SDA_READ(void)

{

//return GPIO_ReadInputPin(IIC_GPIOx, IIC_SDA_GPIO_Pin); return GPIO_ReadInputDataBit(IIC_GPIOx, IIC_SDA_GPIO_Pin); }

//产生起始信号 void IIC_Start(void) {

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set SDA pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow);//set SDA pin as output low Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow);//set SCL pin as output low Delay(); }

//产生停止信号 void IIC_Stop(void) {

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow);//set SDA pin as output low

Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set SDA pin as output high Delay(); }

//等待响应信号

//0--接收应答成功 1-接收应答失败 unsigned char IIC_Wait_Ack(void) {

unsigned char ucErrTime = 0;

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_In_PU_No_IT); //set sda as input with pull up

while(SDA_READ()) {

ucErrTime++; if(ucErrTime > 250) {

IIC_Stop(); return 1; }

}

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow); //set SCL pin as output low Delay(); return 0; }

//产生ACK信号 void IIC_Ack(void) {

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output low Delay(); //延时

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set SDA pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow);//set SDA pin as output low Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow); //set SCL pin as output low Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow); //set SCL pin as output low Delay();

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set

SDA pin as output high Delay(); }

//No ACK

void IIC_NAck(void) {

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow); //set SCL pin as output low Delay();

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set SDA pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output high Delay(); //延时

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow);//set SCL pin as output low Delay(); //延时 }

//IIC发送一个字节

void IIC_Send_Byte(unsigned char txd) {

unsigned char i;

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow); //set SCL pin as output low Delay();

for(i = 0; i < 8; i++) {

if(txd & 0x80) {

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set SDA pin as outputhigh } else {

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow);//set SDA pin as output low } txd <<= 1;

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow); //set SCL pin as output low Delay(); } }

//读取一个字节

unsigned char IIC_Read_Byte(unsigned char ack) {

unsigned char i, res = 0;

GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_In_PU_No_IT); //set sda as

input with pull up for(i = 0; i < 8; ++i ){

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow);//set SCL pin as output high Delay();

GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output high Delay(); res <<= 1; if(SDA_READ()){ res ++; } } return res; } //写数据

unsigned char BQ25890x_write_reg(unsigned char *pBuffer,unsigned char WriteAddr,unsigned char NumToWrite) {

unsigned char u_wait_err = 0;

IIC_Start();

IIC_Send_Byte(SlaveAddress << 1);//slave addr u_wait_err |= IIC_Wait_Ack();

IIC_Send_Byte(WriteAddr); //register addr u_wait_err |= IIC_Wait_Ack();

while(NumToWrite--) {

IIC_Send_Byte(*pBuffer); u_wait_err |= IIC_Wait_Ack(); pBuffer++; }

IIC_Stop();

if(u_wait_err == 0) return 0; return 1; } //

unsigned char BQ25890x_read_reg(unsigned char *pBuffer,unsigned char WriteAddr,unsigned char NumToRead) {

unsigned char u_wait_err = 0;

IIC_Start();

IIC_Send_Byte(SlaveAddress<<1); // SlaveAddress 0x7e u_wait_err |= IIC_Wait_Ack(); IIC_Send_Byte(WriteAddr); // address u_wait_err |= IIC_Wait_Ack();

IIC_Start();

IIC_Send_Byte((SlaveAddress<<1)+1); // SlaveAddress 0x7e u_wait_err |= IIC_Wait_Ack();

while(--NumToRead) {

*pBuffer = IIC_Read_Byte(1); IIC_Ack(); pBuffer++; }

*pBuffer = IIC_Read_Byte(1);

IIC_NAck(); IIC_Stop();

if(u_wait_err == 0) return 0; return 1; }

好了,这就是这部分的内容了。

#include \#include \

#include \

#define AT24C32_SETSDAIN GPIO_Init(AT24C32_SDA_PORT, GPIO_MODE_IN_FL_NO_IT)

#define AT24C32_SETSDAOUT GPIO_Init(AT24C32_SDA_PORT, GPIO_MODE_OUT_OD_LOW_SLOW)

#define I2C_SLAW 0xA0 /*器件地址选择及写标志*/ #define I2C_SLAR 0xA1 /*器件地址选择及读标志*/

GPIO_PIN_6, GPIO_PIN_6,

void nops(void) {

// asm(\// asm(\ uint16_t i = 0; for (; i < 5; i++); }

// 总线复位

void I2C_Reset(void) {

AT24C32_SCL_HIGH; AT24C32_SDA_HIGH; }

// I2C操作严重错误 void I2C_Error(void) {

//复位I2C总线 I2C_Reset();

//进入死循环 while (1) { } }

// 发送起始条件

void I2C_Start_A(void) /*起始条件*/ {

AT24C32_SCL_HIGH; nops();

AT24C32_SDA_LOW; nops();

AT24C32_SCL_LOW; nops(); }

// 停止条件

void I2C_Stop_A(void) {

AT24C32_SDA_LOW; nops();

AT24C32_SCL_HIGH; nops();

AT24C32_SDA_HIGH; nops();

AT24C32_SCL_LOW; nops(); }

// 产生一个时钟信号

uint8_t I2C_GenerateClock(void) {

uint8_t bData = 0; uint16_t t = 0;

AT24C32_SCL_HIGH; nops();

for (t = 0; t < 6; t++);

if (AT24C32_READSDA) {

bData = 1; }

AT24C32_SCL_LOW; nops();

return bData; }

// 应答位

void I2C_Ack(uint8_t bAckYes) {

if (bAckYes) {

AT24C32_SDA_LOW; } else {

AT24C32_SDA_HIGH; }

I2C_GenerateClock();

AT24C32_SDA_HIGH; }

// 发送数据子程序, ucData为要求发送的数据 uint8_t I2C_Send(uint8_t ucData) {

uint8_t i;

for (i = 0; i < 8; i++) {

if (ucData & 0x80) {

AT24C32_SDA_HIGH; } else {

AT24C32_SDA_LOW; }

ucData <<= 1;

I2C_GenerateClock(); }

AT24C32_SDA_HIGH;

return (!I2C_GenerateClock()); }

// 读一个字节的数据,并返回该字节值 uint8_t I2C_Read(void) {

uint8_t ucData = 0; uint8_t i;

for (i = 0; i < 8; i++) {

ucData <<= 1;

if (I2C_GenerateClock()) {

ucData |= 1; } }

return ucData; }

// 设置下一步操作的地址(一字节地址) uint8_t I2C_SetAddress(uint16_t u16Addr) {

// 发送启动信号 I2C_Start_A();

// 发送访问地址

return (I2C_Send(I2C_SLAW) && I2C_Send(u16Addr)); }

// 设置下一步操作的地址(两字节地址) uint8_t I2C_SetAddress16(uint16_t u16Addr) {

// 发送启动信号 I2C_Start_A();

// 发送从器件地址

// 发送访问地址

return (I2C_Send(I2C_SLAW) && I2C_Send(u16Addr >> 8) && I2C_Send(u16Addr & 0xff)); }

// 向8位地址的器件( 如:24C02 )写数据 bAddressIs16bit = 0 // 向16位地址的器件( 如:24C32 )写数据 bAddressIs16bit = 1

void Write_Byte_24c32(uint8_t *pDat, uint16_t u16Addr, uint8_t ucNbyte, uint8_t bAddressIs16bit) {

uint8_t bWriteError = FALSE; //写数据出错标志位 uint8_t i;

uint8_t ucDataBuf = 0; uint32_t Cnt = 0;

for (i = 0; i < ucNbyte; i++) {

if (bAddressIs16bit) {

if (I2C_SetAddress16(u16Addr + i) == 0) {

bWriteError = TRUE; break; } } else {

if (I2C_SetAddress(u16Addr + i) == 0) {

bWriteError = TRUE; break; } }

ucDataBuf = *(pDat + i);

if (I2C_Send(ucDataBuf) == 0) {

bWriteError = TRUE; break; }

I2C_Stop_A();

ucDataBuf = 12; do {

I2C_Start_A();

} while ((++Cnt < 500000) && I2C_Send(I2C_SLAW) == 0);

//如果50mS内还没有响应,则进入保护性报警状态 if (Cnt == 500000) {

bWriteError = TRUE; break; }

I2C_Stop_A(); }

if (bWriteError) {

I2C_Error(); } }

// 从8位地址的器件( 如:24C02 )读数据 bAddressIs16bit = 0 // 从16位地址的器件( 如:24C32 )读数据 bAddressIs16bit = 1

void Read_nByte_24c32(uint8_t *pDat, uint16_t u16Addr, uint8_t ucNbyte, uint8_t bAddressIs16bit) {

uint8_t bReadError标志寄存器 = FALSE; //读EEPROM错误标志位 uint8_t i;

uint8_t ucDataBuf = 0;

if (bAddressIs16bit) {

if (I2C_SetAddress16(u16Addr) == 0) {

bReadError = TRUE; } } else {

if (I2C_SetAddress(u16Addr) == 0) {

bReadError = TRUE; } }

if (bReadError) {

I2C_Error(); }

I2C_Start_A();

if (I2C_Send(I2C_SLAR) == 0) {

bReadError = TRUE; }

if (bReadError) {

I2C_Error(); }

for (i = 0; i < ucNbyte; i++) {

ucDataBuf = I2C_Read();

*(pDat + i) = ucDataBuf; I2C_Ack(i != (ucNbyte - 1)); }

I2C_Stop_A(); }

uint8_t Read_Byte_24c32(uint16_t u16Addr) {

uint8_t EepromDataBuf = 0xFF;

//从16位地址的器件( 如:24C32 )读数据 bAddressIs16bit = 1

Read_nByte_24c32(&EepromDataBuf, u16Addr, 1, DEVICE_ADDR);

return EepromDataBuf; }

//修改EEPROM数据

void ModifData_24c32(uint16_t u16Addr, uint8_t *pDat, uint16_t uclen) {

//向16位地址的器件( 如:24C32 )写数据 bAddressIs16bit = 1 Write_Byte_24c32(pDat, u16Addr, uclen, DEVICE_ADDR); } 1. STM8I/O口模拟I2C所读数据不正确 2. STM8 I/O口模拟I2C 3. 4.

5. #define I2C_ERR 0 6.

7. #define I2C_CRR 1 8.

9. #define I2CDataIn 1 10.

11. #define I2CDataOut 0 12.

13. #define I2C_PORT (GPIOC) 14.

15. #define I2CSCL (GPIO_PIN_7) 16.

17. #define I2CSDA (GPIO_PIN_6) 18. 19.

20. //*************************************************************** 21.

22. // I2C Data input/output 23.

24. // 0-Output, 1-Input 25.

26. //*************************************************************** 27.

28. void I2CDataInOut(bool InOut)

29. 30. { 31.

32. if(InOut) 33. 34. { 35.

36. GPIO_Init(I2C_PORT,I2CSDA,GPIO_MODE_IN_FL_NO_IT); 37. 38. } 39.

40. else

41. 42. { 43.

44. GPIO_Init(I2C_PORT,I2CSDA,GPIO_MODE_OUT_OD_LOW_FAST); 45. 46. } 47.

48. } 49.

50. //*************************************************************** 51.

52. // Send start condition 53.

54. // ensure data is high then issue a start condition 55.

56. // see also i2c_Start() macro 57.

58. //*************************************************************** 59.

60. void I2C_Start (void) 61. 62. { 63.

64. GPIO_WriteHigh(I2C_PORT, I2CSDA); 65.

66. _delay_5us(5); 67.

68. GPIO_WriteHigh(I2C_PORT, I2CSCL); 69.

70. _delay_5us(5); 71.

72. GPIO_WriteLow(I2C_PORT, I2CSDA); 73.

74. _delay_5us(5); 75. 76. } 77.

78. //*************************************************************** 79.

80. // Send stop condition 81.

82. // data low-high while clock high 83.

84. //*************************************************************** 85.

86. void I2C_Stop (void) 87. 88. { 89.

90. GPIO_WriteLow(I2C_PORT, I2CSDA); 91.

92. _delay_5us(5); 93.

94. GPIO_WriteHigh(I2C_PORT, I2CSCL); 95.

96. _delay_5us(5); 97.

98. GPIO_WriteHigh(I2C_PORT, I2CSDA);

99. 100. } 101.

102. //*************************************************************** 103.

104. //ROUTINE NAME : I2C_Ack 105.

106. //INPUT/OUTPUT : None. 107.

108. //DESCRIPTION : Acknoledge generation from now. 109.

110. //COMMENTS : Transfer sequence = DATA, ACK.

111.

112. //*************************************************************** 113.

114. void I2C_Rack(void) 115. 116. { 117.

118. GPIO_WriteLow(I2C_PORT, I2CSDA); 119.

120. _delay_5us(5); 121.

122. GPIO_WriteHigh(I2C_PORT, I2CSCL);

123.

124. _delay_5us(5); 125.

126. GPIO_WriteLow(I2C_PORT, I2CSCL); 127.

128. _delay_5us(5); 129. 130. } 131. 132.

133. //*************************************************************** 134.

135. //ROUTINE NAME : I2C_nAck 136.

137. //INPUT/OUTPUT : None. 138.

139. //DESCRIPTION : Non acknoledge generation from now. 140.

141. //COMMENTS : Transfer sequence = DATA, NACK. 142.

143. //*************************************************************** 144.

145. void I2C_nAck (void) 146. 147. { 148.

149. GPIO_WriteHigh(I2C_PORT, I2CSDA); 150.

151. _delay_5us(5); 152.

153. GPIO_WriteHigh(I2C_PORT, I2CSCL); 154.

155. _delay_5us(5); 156.

157. GPIO_WriteLow(I2C_PORT, I2CSCL); 158.

159. _delay_5us(5); 160. 161. }

162.

163. //*************************************************************** 164.

165. // Send a byte to the slave 写一个数据没有应答

166.

167. // return I2C_ERR OR I2C_CRR 168.

169. //*************************************************************** 170.

171. bool SendByte(UCHAR I2cData) 172. 173. {

174.

175. UCHAR i; 176.

177. bool I2CStatus; 178. 179.

180. for(i=0; i<8; i++) 181. 182. { 183.

184. GPIO_WriteLow(I2C_PORT, I2CSCL); 185.

186. _delay_5us(5); 187.

188. if(I2cData & 0x80) 189.

190. {GPIO_WriteHigh(I2C_PORT, I2CSDA);} 191.

192. else 193.

194. {GPIO_WriteLow(I2C_PORT, I2CSDA);} 195.

196. GPIO_WriteHigh(I2C_PORT, I2CSCL); 197.

198. _delay_5us(5); 199.

200. I2cData <<= 1;

201. 202. } 203.

204. GPIO_WriteLow(I2C_PORT, I2CSCL); 205.

206. GPIO_WriteHigh(I2C_PORT, I2CSDA);//发送完一字节,接收应答 207. 208. 209.

210. I2CDataInOut(I2CDataIn); 211. 212.

213. GPIO_WriteHigh(I2C_PORT, I2CSCL); 214.

215. _delay_5us(5); 216.

217. if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 0) 218.

219. { 220.

221. I2CStatus = I2C_CRR; 222.

223. } 224.

225. else 226.

227. { 228.

229. I2CStatus = I2C_ERR; 230.

231. } 232.

233. I2CDataInOut(I2CDataOut); 234.

235. return I2CStatus; 236.

237. } 238. 239.

240. //*************************************************************** 241.

242. //ROUTINE NAME : I2Cm_RxData 243.

244. //INPUT/OUTPUT : Last byte to receive flag (active high)/Received data byte

.

245.

246. //DESCRIPTION : Receive a data byte. 247.

248. //COMMENTS : Transfer sequence = DATA, ACK, EV7... 249.

250. //*************************************************************** 251.

252. UCHAR RcvByte(void) 253.

254. { 255.

256. UCHAR i; 257.

258. UCHAR ReadByte=0; 259.

260. GPIO_WriteHigh(I2C_PORT, I2CSDA); 261. 262.

263. I2CDataInOut(I2CDataIn); 264.

265. _delay_5us(10); 266.

267. for(i=0; i<8; i++) 268. 269. { 270.

271. ReadByte <<= 1; 272.

273. GPIO_WriteLow(I2C_PORT, I2CSCL); 274.

275. _delay_5us(5); 276.

277. GPIO_WriteHigh(I2C_PORT, I2CSCL); 278.

279. _delay_5us(5); 280. 281.

282. if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 1) 283.

284. {ReadByte |= 0x01;} 285.

286. _delay_5us(5);

287.

288. } 289.

290. GPIO_WriteLow(I2C_PORT, I2CSCL); 291.

292. I2CDataInOut(I2CDataOut); 293.

294. _delay_5us(10);

295.

296. return ReadByte; 297. 298. } 299. 300.

301. /******************************************************* 302.

303. 读N个数据,参数:?

304.

305. wrDAdr: write device-address 写器件地址?? 306.

307. wordAdr: word address 读数据的寄存器地址?? 308.

309. rdDAdr: read device-address 读器件地址 310.

311. *pRdDat: p->read data 读数据指针 312.

313. num: number 需要读数据的个数

314.

315. *******************************************************/ 316.

317. bool I2C_Read(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pRdDat,UCHAR num) 318. 319. { 320.

321. bool I2CAck; 322.

323. UCHAR i=0; 324.

325. UCHAR rdDAdr;

326.

327. rdDAdr = wrDAdr+1; //读器件地址为写地址加1 328.

329. I2C_Start(); /*启动I2C*/

330.

331. _delay_5us(5); 332.

333. I2CAck = SendByte(wrDAdr); /*发写器件地址*/ 334.

335. if(!I2CAck) 336. 337. {

338.

339. return I2C_ERR; 340. 341. } 342.

343. I2CAck = SendByte(wordAdr); /*发寄存器地址*/ 344.

345. if(!I2CAck)

346. 347. { 348.

349. return I2C_ERR; 350. 351. } 352.

353.

354. I2C_Start(); /*重启I2C*/

355.

356. I2CAck = SendByte(rdDAdr); /*发读器件地址*/ 357.

358. if(!I2CAck) 359. 360. { 361.

362. return I2C_ERR; 363. 364. }

365.

366. _delay_5us(5); 367.

368. for(i=0;i

372. *(pRdDat+i) = RcvByte(); 373.

374. I2C_Rack(); 375.

376. }

377.

378. if(i==num-1) 379. 380. { 381.

382. *(pRdDat+i) = RcvByte(); 383.

384. I2C_nAck(); 385. 386. } 387.

388. I2C_Stop();

389.

390. return I2C_CRR; 391. 392. } 393. 394.

395. /******************************************************* 396.

397. 写N个数据,前N-1个要应答,最后一个不要应答 398.

399. wrDAdr: write device-address 写器件地址?? 400.

401. wordAdr: word address 写数据的寄存器地址? 402.

403. *pWrDat: p->write data 写数据指针 404.

405. num: number 需要写入的数据个数

406.

407. *******************************************************/ 408.

409. bool I2C_Write(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pWrDat,UCHAR num) 410. 411. { 412.

413. bool I2CAck; 414.

415. unsigned char i;

416. 417.

418. I2C_Start(); /*启动I2C*/

419.

420. _delay_5us(5); 421.

422. I2CAck = SendByte(wrDAdr); /*发写器件地址*/ 423.

424. if(!I2CAck) 425. 426. { 427.

428. return I2C_ERR; 429. 430. } 431.

432. I2CAck = SendByte(wordAdr); /*发要写的寄存器地址*/ 433.

434. if(!I2CAck) 435. 436. { 437.

438. return I2C_ERR; 439.

440. } 441.

442. for(i=0;i

446. I2CAck = SendByte(*(pWrDat+i)); 447.

448. if(!I2CAck) 449.

450. {return I2C_ERR;} 451. 452. } 453.

454. if(i==num-1)

455. 456. { 457.

458. I2CAck = SendByte(*(pWrDat+num-1)); 459.

460. if(!I2CAck) 461.

462. {return I2C_ERR;} 463. 464. } 465.

466. I2C_Stop(); 467.

468. return I2CAck; 469. 470. }

以上代码不知为何读出数据不正确,用示波器看我发送的器件地址,寄存器地址这些都对,器件输出的数据是0xFF,程序中读出返回的数据是0x00,弄了一天没对相当郁闷,同志们指点下

终于搞定了, 应该跟我的器件有关,另外if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 1)这种不能写成==1,要直接写成if(GPIO_ReadInputPin(I2C_PORT,I2CSDA)),太郁闷了

本文来源:https://www.bwwdw.com/article/3d4.html

Top