[AVR单片机] AVR的IIC总线编程遇到一个问题

[复制链接]
1520|1
 楼主| zl101lz 发表于 2015-8-9 17:22 | 显示全部楼层 |阅读模式
本帖最后由 zl101lz 于 2015-8-9 19:49 编辑

以下代码是运行OK的 atmega16接了一个eeprom(AT240C02A)
会记录开机的次数
  1. #include <iom16v.h>
  2. #include <macros.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int


  5. //I2C 状态定义
  6. //MT 主方式传输 MR 主方式接受
  7. ///////////////////////////////////////////////////
  8. #define START    0x08
  9. #define RE_START   0x10
  10. #define MT_SLA_ACK   0x18
  11. #define MT_SLA_NOACK 0x20
  12. #define MT_DATA_ACK   0x28
  13. #define MT_DATA_NOACK 0x30
  14. #define MR_SLA_ACK   0x40
  15. #define MR_SLA_NOACK 0x48
  16. #define MR_DATA_ACK   0x50
  17. #define MR_DATA_NOACK 0x58  

  18. #define RD_DEVICE_ADDR 0xA1   //前4位器件固定,后三位看连线,最后1位是读写指令位
  19. #define WD_DEVICE_ADDR 0xA0

  20. //常用TWI操作(主模式写和读)
  21. #define Start()                    (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))           //启动I2C
  22. #define Stop()                    (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))           //停止I2C
  23. #define Wait()                    {while(!(TWCR&(1<<TWINT)));}                                             //等待中断发生
  24. #define TestAck()           (TWSR&0xf8)                                                                                                  //观察返回状态
  25. #define SetAck                    (TWCR|=(1<<TWEA))                                                                                //做出ACK应答
  26. #define SetNoAck                   (TWCR&=~(1<<TWEA))                                                                        //做出Not Ack应答
  27. #define Twi()                            (TWCR=(1<<TWINT)|(1<<TWEN))                                        //启动I2C
  28. #define Write8Bit(x)         {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}           //写数

  29. unsigned char smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
  30. unsigned char smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};

  31. uchar table[8]={0,0,0,0,0,0,0,0};

  32. void init(void)
  33. {
  34. DDRB=0xff;
  35. PORTB=0;

  36. DDRC=0x78;//01111000
  37. PORTC=0;
  38. }

  39. void delay(void)
  40. {
  41. uint a;
  42. for(a=0;a<300;a++);
  43. }

  44. void display(uchar *p)
  45. {
  46. uchar i;
  47. for(i=0;i<8;i++)
  48. {
  49.   PORTB=smg_du[*p];
  50.   p++;
  51.   PORTC=smg_we[i];
  52.   delay();
  53. }

  54. }

  55. void twi_init(void)
  56. {
  57. TWBR=0x20;
  58. TWCR=0x04;
  59. TWSR=0;
  60. }

  61. uchar IIC_Write(uchar wdata,uchar addr)
  62. {
  63. Start();
  64. Wait();
  65. if(TestAck()!=START)
  66. return 1;

  67. Write8Bit(WD_DEVICE_ADDR);
  68. Wait();
  69. if(TestAck()!=MT_SLA_ACK)
  70. return 1;

  71. Write8Bit(addr);
  72. Wait();
  73. if(TestAck()!=MT_DATA_ACK)
  74. return 1;

  75. Write8Bit(wdata);
  76. Wait();
  77. if(TestAck()!=MT_DATA_ACK)
  78. return 1;

  79. Stop();
  80. return 0;

  81. }

  82. uchar IIC_Read(uchar addr)
  83. {
  84. uchar temp;

  85. Start();
  86. Wait();
  87. if(TestAck()!=START)
  88. return 1;

  89. Write8Bit(WD_DEVICE_ADDR);
  90. Wait();
  91. if(TestAck()!=MT_SLA_ACK)
  92. return 1;

  93. Write8Bit(addr);
  94. Wait();
  95. if(TestAck()!=MT_DATA_ACK)
  96. return 1;

  97. Start();
  98. Wait();
  99. if(TestAck()!=RE_START)
  100. return 1;

  101. Write8Bit(RD_DEVICE_ADDR);
  102. Wait();
  103. if(TestAck()!=MR_SLA_ACK)
  104. return 1;

  105. Twi();
  106. Wait();
  107. if(TestAck()!=MR_DATA_NOACK)
  108. return 1;

  109. temp=TWDR;
  110. Stop();
  111. return temp;

  112. }

  113. void main(void)
  114. {
  115. uchar i;
  116. init();
  117. twi_init();
  118. i=IIC_Read(0x03);
  119. table[1]=i;
  120. i++;
  121. i=i%10;
  122. IIC_Write(i,0x03);
  123. table[0]=i;

我修改成以下的样子,其实就是加了两行代码,原来是IIC_READ→IIC_WRITE,现在改成IIC_READ→IIC_WRITE→IIC_READ结果就不行了

  1. #include <iom16v.h>
  2. #include <macros.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int


  5. //I2C 状态定义
  6. //MT 主方式传输 MR 主方式接受
  7. ///////////////////////////////////////////////////
  8. #define START    0x08
  9. #define RE_START   0x10
  10. #define MT_SLA_ACK   0x18
  11. #define MT_SLA_NOACK 0x20
  12. #define MT_DATA_ACK   0x28
  13. #define MT_DATA_NOACK 0x30
  14. #define MR_SLA_ACK   0x40
  15. #define MR_SLA_NOACK 0x48
  16. #define MR_DATA_ACK   0x50
  17. #define MR_DATA_NOACK 0x58  

  18. #define RD_DEVICE_ADDR 0xA1   //前4位器件固定,后三位看连线,最后1位是读写指令位
  19. #define WD_DEVICE_ADDR 0xA0

  20. //常用TWI操作(主模式写和读)
  21. #define Start()                    (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))           //启动I2C
  22. #define Stop()                    (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))           //停止I2C
  23. #define Wait()                    {while(!(TWCR&(1<<TWINT)));}                                             //等待中断发生
  24. #define TestAck()           (TWSR&0xf8)                                                                                                  //观察返回状态
  25. #define SetAck                    (TWCR|=(1<<TWEA))                                                                                //做出ACK应答
  26. #define SetNoAck                   (TWCR&=~(1<<TWEA))                                                                        //做出Not Ack应答
  27. #define Twi()                            (TWCR=(1<<TWINT)|(1<<TWEN))                                        //启动I2C
  28. #define Write8Bit(x)         {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}           //写数

  29. unsigned char smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
  30. unsigned char smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};

  31. uchar table[8]={0,0,0,0,0,0,0,0};

  32. void init(void)
  33. {
  34. DDRB=0xff;
  35. PORTB=0;

  36. DDRC=0x78;//01111000
  37. PORTC=0;
  38. }

  39. void delay(void)
  40. {
  41. uint a;
  42. for(a=0;a<300;a++);
  43. }

  44. void display(uchar *p)
  45. {
  46. uchar i;
  47. for(i=0;i<8;i++)
  48. {
  49.   PORTB=smg_du[*p];
  50.   p++;
  51.   PORTC=smg_we[i];
  52.   delay();
  53. }

  54. }

  55. void twi_init(void)
  56. {
  57. TWBR=0x20;
  58. TWCR=0x04;
  59. TWSR=0;
  60. }

  61. uchar IIC_Write(uchar wdata,uchar addr)
  62. {
  63. Start();
  64. Wait();
  65. if(TestAck()!=START)
  66. return 1;

  67. Write8Bit(WD_DEVICE_ADDR);
  68. Wait();
  69. if(TestAck()!=MT_SLA_ACK)
  70. return 1;

  71. Write8Bit(addr);
  72. Wait();
  73. if(TestAck()!=MT_DATA_ACK)
  74. return 1;

  75. Write8Bit(wdata);
  76. Wait();
  77. if(TestAck()!=MT_DATA_ACK)
  78. return 1;

  79. Stop();
  80. return 0;

  81. }

  82. uchar IIC_Read(uchar addr)
  83. {
  84. uchar temp;

  85. Start();
  86. Wait();
  87. if(TestAck()!=START)
  88. return 9;

  89. Write8Bit(WD_DEVICE_ADDR);
  90. Wait();
  91. if(TestAck()!=MT_SLA_ACK)
  92. return 8;

  93. Write8Bit(addr);
  94. Wait();
  95. if(TestAck()!=MT_DATA_ACK)
  96. return 7;

  97. Start();
  98. Wait();
  99. if(TestAck()!=RE_START)
  100. return 6;

  101. Write8Bit(RD_DEVICE_ADDR);
  102. Wait();
  103. if(TestAck()!=MR_SLA_ACK)
  104. return 5;

  105. Twi();
  106. Wait();
  107. if(TestAck()!=MR_DATA_NOACK)
  108. return 4;

  109. temp=TWDR;
  110. Stop();
  111. return temp;

  112. }

  113. void main(void)
  114. {
  115. uchar i;
  116. init();
  117. twi_init();
  118. i=IIC_Read(0x03);
  119. table[1]=i;
  120. i++;
  121. i=i%10;
  122. IIC_Write(i,0x03);
  123. table[0]=i;

  124. i=IIC_Read(0x03);                   ☆
  125. table[2]=i;                                ☆



  126. while(1)
  127. {
  128.   display(table);
  129. }

  130. }
就是五角星的那两行,从返回的代码上看是第二次IIC_READ函数里的(TestAck()!=START)返回错误,
是不是IIC当前非空闲所以不能再读啊?

求解决方法
badbud 发表于 2015-8-21 14:50 | 显示全部楼层
加长延迟看看,这种读写大不分都是延迟时间不够
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

6

帖子

0

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