[新手园地] M0助学板学习第二帖:IIC实验

[复制链接]
 楼主| mcsgy 发表于 2011-9-19 23:08 | 显示全部楼层 |阅读模式
本帖最后由 mcsgy 于 2011-9-19 23:31 编辑

  1. //////////////////////////////////////////////////////
  2. //工程名称IIC实验
  3. //日期:2011年9月20日
  4. //作者:mcsgy
  5. //参考:系统函数驱动,Cube的GPIO实验项目
  6. //参考:STM32不完全手册IIC实验部分
  7. //参考:(电子write_cai)https://bbs.21ic.com/frame.php?frameon=yes&referer=http%3A//bbs.21ic.com/icnewest.html
  8. //////////////////////////////////////////////////////
  9. #include "NUC1xx.h"
  10. #include "iic.h"
  11. #define I2C_STA              0x20
  12. #define I2C_STO              0x10
  13. #define I2C_SI               0x08
  14. #define I2C_AA               0x04
  15. //I2C1的功能使能
  16. void I2C_GPIO_Init(void)
  17. {
  18. SYS->GPAMFP.I2C1_SDA_nWR=1;
  19. SYS->GPAMFP.I2C1_SCL_nRD=1;
  20. }
  21. //打开I2C
  22. int32_t I2C_Open(uint32_t u32BusClock)
  23. {
  24. uint32_t divider;                     //I2C clock = I2C source clock / (4*(divider+1))
  25. divider = (uint32_t) (((SystemCoreClock*10)/(u32BusClock * 4) + 5) / 10 - 1); ///* Compute proper divider for I2C clock */
  26. SYSCLK->APBCLK.I2C1_EN = 1;     //使能I2C时钟
  27. SYS->IPRSTC2.I2C1_RST = 1;     //复位I2C设备
  28. SYS->IPRSTC2.I2C1_RST = 0;
  29. I2C1->CON.ENSI = 1;       //使能I2C控制
  30. I2C1->CLK = divider;      //设置I2C波特率400kHz为最大
  31. return 0;
  32. }
  33. //关闭I2C
  34. int32_t I2C_Close(void)
  35. {
  36. I2C1->CON.ENSI = 0;
  37. SYS->IPRSTC2.I2C1_RST = 1;
  38. SYS->IPRSTC2.I2C1_RST = 0;
  39. SYSCLK->APBCLK.I2C1_EN = 0;
  40. return 0;
  41. }
  42. //获取I2C状态
  43. uint32_t I2C_GetStatus(void)
  44. {
  45. return I2C1->STATUS;
  46. }
  47. //写控制位函数
  48. void I2C_Ctrl(uint8_t start, uint8_t stop, uint8_t intFlag, uint8_t ack)
  49. {

  50. uint32_t Reg = 0;
  51.   
  52. if (start)
  53.   Reg |= I2C_STA;
  54. if (stop)
  55.      Reg |= I2C_STO;
  56. if (intFlag)
  57.   Reg |= I2C_SI;
  58. if (ack)
  59.   Reg |= I2C_AA;
  60. *((__IO uint32_t *)&I2C1->CON) = (*((__IO uint32_t *)&I2C1->CON) & ~0x3C) | Reg;      
  61. }
  62. //提数据
  63. uint8_t I2C_ReadData(void)
  64. {        
  65. return I2C1->DATA;
  66. }
  67. //写数据
  68. void I2C_WriteData(uint8_t u8data)
  69. {      
  70. I2C1->DATA = u8data;
  71. }
  72. //写入一个字节函数
  73. void WriteByte(uint16_t addr,uint8_t data)                     //addr 为数据要存储的地址,data为要写入的数据
  74. {
  75. I2C_Open(400000);        //打开IIC1设备
  76. I2C_Ctrl(1,0,1,0);        //启动Start
  77. while(0==(I2C1->CON.SI));
  78. I2C_WriteData(0xA0);       //写从设备地址1010(A2)(A1)(A0)(W/R)
  79. I2C_Ctrl(0,0,1,0);        //清SI标志位
  80. while(0==(I2C1->CON.SI));
  81. I2C_WriteData((uint8_t)(addr/256));    //写AT24C16存储器高地址
  82. I2C_Ctrl(0,0,1,1);
  83. while(0==(I2C1->CON.SI));
  84. I2C_WriteData((uint8_t)(addr%256));    //写AT24C16存储器低地址
  85. I2C_Ctrl(0,0,1,1);
  86. while(0==(I2C1->CON.SI));
  87. I2C_WriteData(data);       //写入数据
  88. I2C_Ctrl(0,0,1,1);
  89. while(0==(I2C1->CON.SI));      //发STOP信号
  90. I2C_Ctrl(0,1,1,0);
  91. I2C_Close();         //关闭IIC1设备
  92. }
  93. uint8_t ReadByte(uint16_t addr)                         //addr 为要读出字节的地址
  94. {
  95. uint8_t temp;
  96. I2C_Open(400000);       //打开IIC1设备
  97. I2C_Ctrl(1,0,1,0);       //发Start信号
  98. while(0==(I2C1->CON.SI));
  99. I2C_WriteData(0xA0);
  100. I2C_Ctrl(0,0,1,0);
  101. while(0==(I2C1->CON.SI));
  102. I2C_WriteData((uint8_t)(addr/256));
  103. I2C_Ctrl(0,0,1,1);
  104. while(0==(I2C1->CON.SI));
  105. I2C_WriteData((uint8_t)(addr%256));
  106. I2C_Ctrl(0,0,1,1);
  107. while(0==(I2C1->CON.SI));
  108. I2C_Ctrl(1,0,1,0);      //发Start信号
  109. while(0==(I2C1->CON.SI));
  110. I2C_WriteData(0xA1);     //发“读”信号
  111. I2C_Ctrl(0,0,1,1);
  112. while(0==(I2C1->CON.SI));
  113. I2C_Ctrl(0,0,1,0);
  114. while(0==(I2C1->CON.SI));
  115. temp=I2C_ReadData();
  116. I2C_Ctrl(0,1,1,0);
  117. I2C_Close();       //关闭IIC1设备
  118. return temp;
  119. }
  120. //设置I2C时钟
  121. int32_t I2C_SetClockFreq(uint32_t u32BusClock)
  122. {
  123.     uint32_t divider;     

  124. divider = (uint32_t) (((SystemCoreClock*10)/(u32BusClock * 4) + 5) / 10 - 1);
  125.   I2C1->CLK = divider;
  126. return 0;
  127. }
  128. //整个I2C初始化函数
  129. void I2C_Init(void)
  130. {
  131. I2C_GPIO_Init();
  132.    I2C_Open(400000);         //打开I2C硬件并配置时钟总线400KHZ;
  133.    I2C_SetClockFreq (400000);//给I2C配置时钟频率;
  134.    I2C_GetStatus ();      //获取I2C状态码;
  135.    I2C_WriteData(0);    //写字节;
  136.    I2C_ReadData();             //读字节;
  137.    I2C_Ctrl(0, 0, 0, 0);   //设定I2C控制位,包括控制寄存器中的STA, STO, AA, SI。
  138. }





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
hotpower 发表于 2011-9-20 06:19 | 显示全部楼层
iic俺感觉还是用状态机更好理解。而且程序不会乱。
 楼主| mcsgy 发表于 2011-9-20 09:25 | 显示全部楼层
2# hotpower

恩,第一次用,能读写我就知足了。继续努力
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:从零开始

6

主题

232

帖子

1

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