主题 : IIC总线驱动问题 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 17673
精华: 0
发帖: 29
金钱: 145 两
威望: 29 点
综合积分: 58 分
注册时间: 2010-03-31
最后登录: 2011-02-24
楼主  发表于: 2010-05-26 16:21

 IIC总线驱动问题

由于准备写一个基于Linux操作系统的IIC总线驱动,所以先把裸机上的程序调试通过后才去开发基于Linux操作系统的,但是有一个小问题,程序都完全按IIC总线时序来书定了,还是有些错误。主要是不能正常定位,即不能选择性读与选择性起始地址后以页的方式进行读取。在这两种方式下,写入到rIICDS地址不能发送出去,一直保存于rIICDS中,所以在对rIICDS进行读时,读到的还是写入到rIICDS中的值。

同时,看了开发板提供的例子,有一点问题,不知道是我理解错了还是什么原因。
一个重大的错误在于rGPECON的设置上。因为IIC的SDA,SCL分别为GPE15与GPE14,而例程在进行GPIO口的初始化时为 rGPECON |= 0xA00000;  这不是把GPE14,GPE15设置为IIC端口,同时,GPE14,GPE15端口没有上端口上拉电阻,而例子中把rGEPUP初始化为 rGPEUP |= 0xC000; 在2440中rGPEUP的有效位只为14位,这样初始有用吗?

下面是我的写的代码,由于本人没有用仿真器,所以不知道错在什么地方,有懂的读者,请帮忙一下。
复制代码
  1. /************************************************
  2. *说明:本程序是S3C2440 IIC总线的一个简单的驱动程序
  3. *     由于本程序比较简单,所以,在此不再进行说明,
  4. *     有不懂的读者请自行阅读相关文档。
  5. *
  6. *     AT24C08 的地址格式为: 1 0 1 0 A2 P1 P0 W/R
  7. *     A2为设备地址位、P1,P0为片内页寻址  LSB=0 写
  8. *     LSB=1 读
  9. *
  10. *CPU          :S3C2440
  11. *编译环境     :ADS1.2
  12. *开发板       :MINI2440
  13. *作者         :soon
  14. *部门         : 长沙理工大学
  15. *               计算机与通信工程学院
  16. *               计算机07级04班
  17. *最后修改时间 :开发中
  18. ************************************************/
  19. #ifndef _MY_IIC_C_
  20. #define _MY_IIC_C_
  21. #include "../include/2440addr.h"
  22. #include "../include/2440lib.h"
  23. #include "../include/def.h"
  24. #include "../include/My_IIC.h"
  25. static int seave_gpecon;
  26. /*用于保存GPECON的当前值,为恢复GPECON做准备*/
  27. U8 write_buffer[16];
  28. /*写缓冲区*/
  29. U8 read_buffer[16];
  30. /*读缓冲区*/
  31. /*初始化GPIO*/
  32. void
  33. _init_gpio(void)
  34. {
  35.     seave_gpecon = rGPECON;
  36.     rGPECON = 0xA0000000;    
  37. }
  38. /*恢复GPIO口*/
  39. void
  40. _resume_gpio(void)
  41. {
  42.     rGPECON = seave_gpecon;
  43. }
  44. /*初始化IIC总线*/
  45. void
  46. _init_iic(void)
  47. {
  48.     /*
  49.     *IIC应答使能有效、IICCLK = FPCLK/16、
  50.     *中断使能、 清除挂取条件、 TXCLK = IICCLK/16
  51.     */
  52.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  53.     rIICSTAT = 0x10;
  54.     rIICADD = 0x10;
  55. }
  56. /*写一个字节到指定地址*/
  57. void
  58. _byte_write(U8 device_address, U8 word_address, U8 data)
  59. {
  60.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  61.     rIICSTAT = (rIICSTAT & 0x0) | (0x1 << 7) | (0x1 << 6);
  62.     rIICDS  = device_address;
  63.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  64.     while((rIICSTAT & 0x01) == 1);
  65.     
  66.     rIICDS = word_address;
  67.     rIICCON &= ~(0x1 << 4);
  68.     while((rIICSTAT & 0x01) == 1);
  69.     
  70.     rIICDS = data;
  71.     rIICCON &= ~(0x1 << 4);
  72.     while((rIICSTAT & 0x01) == 1);
  73.     rIICSTAT &= ~(0x1 << 5);
  74.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  75. }
  76. /*以页的方式写入*/
  77. void _page_write(U8 device_address, U8 word_start_address,U8 *buffer_start_address)
  78. {
  79.     unsigned int i;
  80.     
  81.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  82.     rIICSTAT = (rIICSTAT & 0x0) | (0x1 << 7) | (0x1 << 6);
  83.     rIICDS  = device_address;
  84.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  85.     while((rIICSTAT & 0x01) == 1);
  86.     
  87.     rIICDS = word_start_address;
  88.     rIICCON &= ~(0x1 << 4);
  89.     while((rIICSTAT & 0x01) == 1);
  90.     
  91.     for(i = 0; i < 15; i ++){
  92.         rIICDS = *(buffer_start_address + i);
  93.         rIICCON &= ~(0x1 << 4);
  94.         while((rIICSTAT & 0x01) == 1);
  95.     }
  96.     
  97.     rIICDS = *(buffer_start_address + i);
  98.     rIICCON &= ~(0x1 << 4);
  99.     while((rIICSTAT & 0x01) == 1);
  100.     
  101.     rIICSTAT &= ~(0x1 << 5);
  102.     
  103.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  104. }
  105. /*读当前地址单元内容*/
  106. U8
  107. _current_address_read(U8 device_address)
  108. {
  109.     U8 data;
  110.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  111.     
  112.     rIICSTAT = (rIICSTAT &0x0) | (0x1 << 7) | (0 << 6);
  113.     rIICDS  = device_address;
  114.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  115.     while((rIICSTAT & 0x01) == 1);
  116.     rIICCON = (0 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  117.     data = rIICDS;
  118.     
  119.     rIICSTAT &= ~(0x1 << 5);
  120.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  121.   
  122.     return data;
  123. }
  124. /*读指定单元地址内容*/
  125. U8
  126. _random_address_read(U8 device_address, U8 word_address)
  127. {
  128.     U8 data;
  129.     
  130.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  131.     rIICSTAT = (rIICSTAT & 0x0) | (0x1 << 7) | (0x1 << 6);
  132.     rIICDS  = device_address & 0xFE;
  133.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  134.     while((rIICSTAT & 0x01) == 1);
  135.     
  136.     rIICDS = word_address;
  137.     rIICCON &= ~(0x1 << 4);
  138.     while((rIICSTAT & 0x01) == 1);
  139.     
  140.     
  141.     rIICSTAT = (rIICSTAT & 0x0) | (0x1 << 7) | (0 << 6);
  142.     rIICDS  = device_address;
  143.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  144.     rIICCON &= ~(0x1 << 4);
  145.     while((rIICSTAT & 0x01) == 1);
  146.     rIICCON = (0 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  147.     data = rIICDS;
  148.     
  149.     rIICSTAT &= ~(0x1 << 5);
  150.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  151.   
  152.     return data;
  153. }
  154. /*以页读方式读*/
  155. void
  156. _sequential_address_read(U8 device_address,U8 word_address,U8 *buffer_start_address)
  157. {
  158.     unsigned i;
  159.     
  160.     
  161.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  162.     rIICSTAT = (rIICSTAT & 0x0) | (0x1 << 7) | (0x1 << 6);
  163.     rIICDS  = device_address & 0xFE;
  164.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  165.     while((rIICSTAT & 0x01) == 1);
  166.     rIICDS = word_address;
  167.     rIICCON &= ~(0x1 << 4);
  168.     while((rIICSTAT & 0x01) == 1);
  169.     
  170.     rIICSTAT = (rIICSTAT & 0x0) | (0x1 << 7) | (0 << 6);
  171.     rIICDS  = device_address;
  172.     rIICSTAT |= (0x1 << 5) | (0x1 << 4);
  173.     rIICCON &= ~(0x1 << 4);
  174.     while((rIICSTAT & 0x01) == 1);
  175.     
  176.     for(i = 0; i < 15; i ++){
  177.         *(buffer_start_address + i) = rIICDS;
  178.         rIICCON &= ~(0x1 << 4);
  179.         while((rIICSTAT & 0x01) == 1);
  180.     }
  181.      rIICCON = (0 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  182.     *(buffer_start_address + i) = rIICDS;
  183.     rIICSTAT &= ~(0x1 << 5);
  184.     rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
  185. }
  186. /*用于延时一小段时间*/
  187. void
  188. _delay_time(unsigned int delay_time)
  189. {
  190.     while(delay_time --);
  191. }
  192. /*测试程序*/
  193. void
  194. _test_iic(void)
  195. {
  196.     char i;
  197.     
  198.     /*实始化读 写缓冲区*/
  199.     for( i = 0; i < 16; i ++){
  200.         *(write_buffer + i) = i * 2;
  201.         *(read_buffer + i )= 0;
  202.         }
  203.     
  204.     /*下面为测试按页写测试*/
  205.     
  206.     _page_write(DEVICE_ADDRESS_WRITE,0,write_buffer);
  207.     _delay_time(5);
  208.     
  209.     
  210.     
  211.     
  212.     for(i = 0; i < 16; i ++){
  213.       _byte_write(DEVICE_ADDRESS_WRITE, i,i * 3);
  214.      _delay_time(5000);
  215.     
  216.      Uart_Printf("%d   %d\n",i + 1 ,_current_address_read(DEVICE_ADDRESS_READ));
  217.      _delay_time(10);
  218.     
  219.      }
  220.     
  221.     /*下面为测试随机地址读*/
  222.     for(i = 0; i < 16; i ++){
  223.       Uart_Printf("%d\n",_random_address_read(DEVICE_ADDRESS_READ,i));
  224.       _delay_time(5);
  225.       
  226.       Uart_Printf("%d\n",_current_address_read(DEVICE_ADDRESS_READ));
  227.       _delay_time(5);
  228.       
  229.       }
  230.       
  231.       
  232.     /*下面为测试按页读*/
  233.     _sequential_address_read(DEVICE_ADDRESS_READ,3,read_buffer);
  234.     _delay_time(5);
  235.     
  236.     
  237.     for(i = 0; i < 16; i ++)
  238.         Uart_Printf("%d  %d\n",i + 1,*(read_buffer + i));
  239.     
  240.     
  241.     
  242.     Uart_Printf("\n");
  243. }
  244. #endif
  245. /************************************************
  246. ||
  247. ||
  248. ||
  249. ||            END My_IIC.c
  250. ||
  251. ||
  252. ||
  253. ************************************************/
级别: 新手上路
UID: 17673
精华: 0
发帖: 29
金钱: 145 两
威望: 29 点
综合积分: 58 分
注册时间: 2010-03-31
最后登录: 2011-02-24
1楼  发表于: 2010-05-26 20:58
没有搞过的?在网上找了一天都是一跟开发板上的一样的,真正把AT24C08的两种写入方式,三种读取方式都写出来的没有找到过。
级别: 新手上路
UID: 17673
精华: 0
发帖: 29
金钱: 145 两
威望: 29 点
综合积分: 58 分
注册时间: 2010-03-31
最后登录: 2011-02-24
2楼  发表于: 2010-05-27 12:29
版主呢?看一下吧,版主。在网上的找到的例子几乎都是跟你们提供的开发板的子一样的,这到底是谁抄谁的啊,第一版是谁写的呢?
级别: 新手上路
UID: 30093
精华: 0
发帖: 2
金钱: 10 两
威望: 2 点
综合积分: 4 分
注册时间: 2010-10-11
最后登录: 2017-09-13
3楼  发表于: 2010-10-12 09:53
你这个代码是不是有问题啊?比如rIICCON = (1 << 7) | ( 0 << 6) | (0 << 5) | (0xF);
把第5位设置为0,是不是禁止中断啊,既然禁止了,这一步rIICCON &= ~(0x1 << 4);有什么意义呢?
级别: 新手上路
UID: 34867
精华: 0
发帖: 13
金钱: 70 两
威望: 14 点
综合积分: 26 分
注册时间: 2010-12-22
最后登录: 2012-06-12
4楼  发表于: 2011-02-20 17:44
非中断模式!