[菜农群课笔记] 【第三期】I2C的操作.查询,中断.各种操作!

[复制链接]
4028|9
 楼主| kyzb001 发表于 2011-12-7 12:36 | 显示全部楼层 |阅读模式
I2c, ST, se, ck, AC
本帖最后由 kyzb001 于 2011-12-7 14:22 编辑
  1. void DrcI2C_WriteByte(uint32_t address,uint8_t data )
  2. {
  3. uint32_t i;
  4. SystemCoreClock = DrvSYS_GetHCLKFreq();
  5. //Open I2C1 and set clock = 50Kbps
  6. if(DrvI2C_Open(I2C_PORT1, 50000))
  7. printf("Open i2c1 fail.\n");

  8. //send i2c start state
  9. DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //设置开始
  10. while (I2C1->I2CON.SI == 0); //等待...

  11. I2C1->I2CDAT = 0xA0; //发送器件地址
  12. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1,0 ); //clr si flag
  13. while( I2C1->I2CON.SI == 0 ); //poll si flag

  14. I2C1->I2CDAT = (address>>8)&0XFF; //send address high
  15. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
  16. while( I2C1->I2CON.SI == 0 ); //poll si flag
  17. //send address low
  18. I2C1->I2CDAT = address&0XFF;
  19. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
  20. while( I2C1->I2CON.SI == 0 ); //poll si flag
  21. //send data
  22. I2C1->I2CDAT = data; //write data to
  23. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
  24. while( I2C1->I2CON.SI == 0 ); //poll si flag
  25. //send i2c stop
  26. DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //send stop
  27. while( I2C1->I2CON.STO);
  28. //while( I2C1->CON.SI == 0 );
  29. for(i=0;i<60;i++);
  30. DrvI2C_Close(I2C_PORT1);

  31. for(i=0;i<6000;i++);
  32. for(i=0;i<6000;i++);
  33. }

  34. void DrcI2C_WriteData(uint32_t address,uint8_t *pBuffer ,uint32_t u32Num)
  35. {
  36. uint32_t i;
  37. SystemCoreClock = DrvSYS_GetHCLKFreq();

  38. if(DrvI2C_Open(I2C_PORT1, 50000)) //Open I2C1 and set clock = 50Kbps
  39. printf("Open i2c1 fail.\n");

  40. //send i2c start
  41. DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //set start
  42. while (I2C1->I2CON.SI == 0); //poll si flag
  43. //send writer command
  44. I2C1->I2CDAT = address; //send writer command
  45. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1,0 ); //clr si flag
  46. while( I2C1->I2CON.SI == 0 ); //poll si flag

  47. while(u32Num--)
  48. {
  49. //send data
  50. I2C1->I2CDAT = *pBuffer; //write data to
  51. pBuffer++;
  52. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
  53. while( I2C1->I2CON.SI == 0 ); //poll si flag

  54. }

  55. //send i2c stop
  56. DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //send stop
  57. while( I2C1->I2CON.STO);
  58. //while( I2C1->CON.SI == 0 );
  59. for(i=0;i<60;i++);
  60. DrvI2C_Close(I2C_PORT1);

  61. for(i=0;i<6000;i++);
  62. for(i=0;i<6000;i++);
  63. }

  64. uint8_t DrcI2C_ReadByte(uint32_t address)
  65. {
  66. uint8_t TEMP;
  67. //Open I2C1 and set clock = 50Kbps
  68. SystemCoreClock = DrvSYS_GetHCLKFreq();
  69. DrvI2C_Open(I2C_PORT1, 50000);
  70. //send i2c start
  71. DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //set start
  72. while (I2C1->I2CON.SI == 0); //poll si flag

  73. //send writer command
  74. I2C1->I2CDAT = 0XA0;
  75. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si
  76. while( I2C1->I2CON.SI == 0 ); //poll si flag

  77. //send address high
  78. I2C1->I2CDAT = (address>>8)&0XFF;
  79. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
  80. while( I2C1->I2CON.SI == 0 ); //poll si flag

  81. //send address low
  82. I2C1->I2CDAT = address&0XFF;
  83. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si and set ack
  84. while( I2C1->I2CON.SI == 0 ); //poll si flag

  85. //send start flag
  86. DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //clr si and send start
  87. while( I2C1->I2CON.SI == 0 ); //poll si flag

  88. //send read command
  89. I2C1->I2CDAT = 0XA1;
  90. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si
  91. while( I2C1->I2CON.SI == 0 ); //poll si flag

  92. //resive data
  93. I2C1->I2CDAT = 0XFF;
  94. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si
  95. while( I2C1->I2CON.SI == 0 ); //poll si flag
  96. TEMP= I2C1->I2CDAT;
  97. //send i2c stop
  98. DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //clr si and set stop
  99. while( I2C1->I2CON.STO);
  100. DrvI2C_Close(I2C_PORT1);

  101. return TEMP;
  102. }

  1. #include "DrvI2C_Int.h"

  2. volatile I2C_HOT_T I2C1s;



  3. void I2C1_INT_HANDLE (uint32_t status)
  4. {
  5. switch(status & 0xf8)
  6. {
  7. case I2C_START: //主机收到自己发送的开始信号
  8. {
  9. if(I2C1s.State == I2C_START)
  10. { //本次中断应该接收TW_START信号
  11. I2C1->I2CDAT = I2C1s.u8SetAddress & 0xfe; //发送子机地址(写)
  12. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //STA位必须清除,否则死机 清除中断标志
  13. I2C1s.State = I2C_MT_SLA_ACK; //Status下次I2C_MT_SLA_ACK
  14. }
  15. else
  16. I2C_Exit(); //通讯失败
  17. break;
  18. }

  19. case I2C_REP_START: //主机收到自己发送的重新开始信号
  20. {
  21. if (I2C1s.State == I2C_REP_START)
  22. { //本次中断应该接收TW_RESTART信号
  23. I2C1->I2CDAT = I2C1s.u8SetAddress; //发送子机地址(读)
  24. I2C1s.State = I2C_MR_SLA_ACK; //Status下次I2C_MR_SLA_ACK
  25. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //STA位必须清除,否则死机 清除中断标志
  26. }
  27. else
  28. I2C_Exit(); //通讯失败
  29. break;
  30. }

  31. case I2C_MT_SLA_ACK:
  32. { //主发机接收到从机的地址应答信号后发送命令
  33. if(I2C1s.State == I2C_MT_SLA_ACK)
  34. { //本次中断应该接收TW_MT_SLA_ACK信号
  35. I2C1s.State = I2C_MT_DATA_ACK; //Status下次应该收TW_MT_DATA_ACK
  36. I2C1->I2CDAT = I2C1s.SubComm; //发送子机命令
  37. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
  38. }
  39. else
  40. I2C_Exit(); //通讯失败
  41. break;
  42. }

  43. case I2C_MR_SLA_ACK:
  44. { //主收机接收到从机的地址应答信号
  45. if ((I2C1s.State == I2C_MR_SLA_ACK) && I2C1s.u32SubCount)
  46. { //本次中断应该接收TW_MR_SLA_ACK信号
  47. I2C1s.State = I2C_MR_DATA_ACK; //Status下次应该收TW_MR_DATA_ACK
  48. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
  49. }
  50. else
  51. I2C_Exit(); //通讯失败
  52. break;
  53. }
  54. case I2C_MT_DATA_ACK:
  55. { //主收机接收到从机的数据应答信号
  56. if ((I2C1s.State == I2C_MT_DATA_ACK) && (I2C1s.u32Count < I2C1s.u32MasterCount))
  57. { //本次中断应该接收TW_MT_DATA_ACK信号
  58. I2C1->I2CDAT= I2C1s.u32TxBuffer[I2C1s.u32Count ++]; //发送子机数据
  59. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
  60. }
  61. else
  62. {
  63. if ((I2C1s.State == I2C_MT_DATA_ACK) &&
  64. (I2C1s.u32Count == I2C1s.u32MasterCount) &&
  65. (I2C1s.u8SetAddress & 0x01))
  66. { //本次中断应该接收TW_MT_DATA_ACK信号
  67. I2C_REStart();//
  68. }
  69. else
  70. I2C_Stop(); //通讯成功
  71. }
  72. break;
  73. }
  74. case I2C_MR_DATA_ACK:
  75. {
  76. if ((I2C1s.State == I2C_MR_DATA_ACK) && (I2C1s.u32Count < I2C1s.u32SubCount))
  77. {
  78. I2C1s.u32TxBuffer[I2C1s.u32Count ++] = I2C1->I2CDAT;//接收子机数据
  79. if (I2C1s.u32Count < I2C1s.u32SubCount)
  80. {
  81. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
  82. }
  83. else
  84. {
  85. DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  86. I2C1s.State = I2C_MR_DATA_NACK; //下次进入I2C_MR_DATA_NACK,接收数据准备完成
  87. }
  88. }
  89. else
  90. I2C_Exit(); //通讯失败
  91. break;
  92. }
  93. case I2C_MR_DATA_NACK: //数据接收结束
  94. {
  95. if((I2C1s.State == I2C_MR_DATA_NACK) && (I2C1s.u32Count == I2C1s.u32SubCount))
  96. {
  97. I2C_Stop(); //通讯成功
  98. }
  99. else
  100. I2C_Exit(); //通讯失败
  101. break;
  102. }

  103. default:
  104. I2C_Exit(); //通讯失败
  105. }
  106. }

  107. void Init_I2C(void)
  108. {
  109. /* Set I2C I/O */
  110. DrvGPIO_InitFunction(E_FUNC_I2C1);
  111. I2C1s.u8SetAddress = 0xA0;
  112. }

  113. void I2C_Start(void)
  114. {
  115. I2C1s.Busy = TRUE;
  116. I2C1s.State = I2C_START; //主机准备发送启始位
  117. I2C1s.u32Count = 0; //发送数据个数
  118. //SystickCount = 0; //清除节拍计数器

  119. /* Open I2C1, and set clock = 50Kbps */
  120. DrvI2C_Open(I2C_PORT1,50000);

  121. /* Enable I2C1 interrupt and set corresponding NVIC bit */
  122. DrvI2C_EnableInt(I2C_PORT1);

  123. /* Install I2C1 call back function for slave */
  124. DrvI2C_InstallCallback(I2C_PORT1, I2CFUNC, I2C1_INT_HANDLE);

  125. DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0);

  126. DrvSYS_Delay(8000);
  127. }

  128. void I2C_REStart(void)
  129. {
  130. I2C1s.Busy = TRUE;
  131. I2C1s.State = I2C_REP_START; //主机准备发送启始位
  132. I2C1s.u32Count = 0; //发送数据个数
  133. DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0);
  134. }


  135. void I2C_Stop(void)
  136. {
  137. I2C1s.Busy= FALSE;
  138. I2C1s.State = I2C_BUS_OK; //通讯成功
  139. DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);
  140. }

  141. void I2C_Exit(void)
  142. {
  143. I2C1s.Busy = FALSE;
  144. I2C1s.State = I2C_BUS_ERROR; //通讯失败
  145. DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);

  146. printf("I2C talk is fail.\n");
  147. }


  148. unsigned char I2C_ReadByte(unsigned int Address, unsigned char *Data)
  149. {
  150. I2C1s.u8SetAddress |= 0x01;
  151. I2C1s.u32MasterCount = 0; //发送0个数据(只读)
  152. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  153. I2C1s.SubComm = Address; //读出地址
  154. I2C1s.u32SubCount = 1; //接收1个数据
  155. I2C_Start(); //启动I2C模块
  156. if (I2C1s.State == I2C_BUS_OK) //通讯成功
  157. {
  158. Data[0] = I2C1s.u32TxBuffer[0]; //从接收缓冲区取出一个字节
  159. }
  160. return I2C1s.State; //(读出数据在RxBuffer[0]~RxBuffer[15])
  161. }
  162. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  163. unsigned char I2C_ReadBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
  164. {
  165. int i;
  166. I2C1s.u8SetAddress |= 0x01;
  167. I2C1s.u32MasterCount = 0; //发送0个数据(只读)

  168. I2C1s.SubComm = Address; //读出地址
  169. I2C1s.u32SubCount = (Cnt <= sizeof(I2C1s.u32TxBuffer)) ? Cnt : sizeof(I2C1s.u32TxBuffer);//接收Cnt个数据
  170. I2C_Start(); //启动I2C模块
  171. if (I2C1s.State == I2C_BUS_OK)
  172. { //通讯成功
  173. for (i = 0; i < I2C1s.u32SubCount; i ++)
  174. Data[i] = I2C1s.u32TxBuffer[i]; //从接收缓冲区取出Cnt个字节
  175. }
  176. return I2C1s.State; //(读出数据在RxBuffer[0]~RxBuffer[15])
  177. }
  178. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  179. unsigned char I2C_WriteByte(unsigned int Address, unsigned char Data)
  180. {
  181. I2C1s.u8SetAddress &=0xfe;
  182. I2C1s.u32MasterCount = 1; //发送1个数据

  183. I2C1s.SubComm = Address; //写入地址
  184. I2C1s.u32TxBuffer[0] = Data; //写入1个数据到发送缓冲区
  185. I2C1s.u32SubCount = 0; //接收0个数据
  186. I2C_Start(); //启动I2C模块
  187. DrvSYS_Delay(100);
  188. return I2C1s.State;
  189. }



  190. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  191. unsigned char I2C_WriteBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
  192. {
  193. int i;
  194. I2C1s.u8SetAddress &= 0xfe; //发送Cnt个数据
  195. I2C1s.u32MasterCount =Cnt ;


  196. I2C1s.SubComm = Address; //写入地址

  197. for (i = 0; i < Cnt; i ++)
  198. {
  199. I2C1s.u32TxBuffer[i] = Data[i]; //写入Cnt个数据到发送缓冲区
  200. }
  201. I2C1s.u32SubCount = 0; //接收0个数据
  202. I2C_Start(); //启动I2C模块
  203. DrvSYS_Delay(100);
  204. return I2C1s.State;
  205. }





其实我是复制黏贴的 - -~
废话不多说了,遇到一个变态的I2C器件...折腾了2天..显示出来了!!
贴上代码!
现在网速度很垃圾~ 贴不上去!   网速好了 在补!!!
Ryanhsiung 发表于 2011-12-7 12:57 | 显示全部楼层
还好了,你遇到的我肯定遇到过,我遇到你不一定遇到!

    呵呵
 楼主| kyzb001 发表于 2011-12-7 13:26 | 显示全部楼层
本帖最后由 kyzb001 于 2011-12-7 13:29 编辑
还好了,你遇到的我肯定遇到过,我遇到你不一定遇到!

    呵呵
Ryanhsiung 发表于 2011-12-7 12:57


不会把, 这么肯定。
我去年7月份就接触M0了!
功能除了USB 其他的都玩过了.....
 楼主| kyzb001 发表于 2011-12-7 13:30 | 显示全部楼层
当时用的是140....
 楼主| kyzb001 发表于 2011-12-7 15:28 | 显示全部楼层
做为查询方式...新塘的那个DrvI2C_Ctrl 这个函数写的很蛋疼~
中断方式DrvI2C_Ctrl这个函数 会使操作方便一点!
不说那个方式好~  最好用的就是最好的!!!
mcs8098 发表于 2011-12-20 11:13 | 显示全部楼层
Ryanhsiung 发表于 2011-12-22 08:46 | 显示全部楼层
不会把, 这么肯定。
我去年7月份就接触M0了!
功能除了USB 其他的都玩过了.....
kyzb001 发表于 2011-12-7 13:26


我指的是I2C的设备
 楼主| kyzb001 发表于 2011-12-22 09:06 | 显示全部楼层
呵呵~ 设备就那么肯定拉!:)
7# Ryanhsiung
qhongzhang 发表于 2011-12-29 15:12 | 显示全部楼层
先谢谢。用查询还,还是中断好呢?
Ryanhsiung 发表于 2012-1-8 12:43 | 显示全部楼层
先谢谢。用查询还,还是中断好呢?
qhongzhang 发表于 2011-12-29 15:12

正常当然是中断好了,占用系统时间少。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:Is this my life

15

主题

624

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部