搜索
bottom↓
回复: 13

请教一个avr twi程序的问题

[复制链接]

出0入0汤圆

发表于 2013-7-7 16:26:38 | 显示全部楼层 |阅读模式
今天上午我用iccv7 for avr写了一个twi总线读写at24c02,记忆开关机的次数,我改了有一个小时都没有把错误改好。
//开机次数的记忆
#include <iom16v.h>
#include <macros.h>
#define uchar  unsigned char
#define uint  unsigned int
//命令定义
//MT 为主机发送  mr 为主机接收
#define START         0X08
#define RE_START      0X10
#define MT_SLA_ACK    0X18
#define MT_SLA_NOACK  0X20
#define MT_DATA_ACK   0X28
#define MT_DATA_NOACK 0X30
#define MR_SLA_ACK    0X40
#define MR_SLA_NOACK  0X48
#define MR_DATA_ACK   0X50
#define MR_DATA_NOACK 0X58
//前四位与器件地址有关
#define   RD_DEVICE_ADDR 0XA1
#define   WD_DEVICE_ADDR 0XA0

//常用twi操作(主模式写和读)
#define start()  (TWCR=(1<<TWINT)|1<<TWSTA)|(1<<TWEN))
#define stop()   (TWCR=(1<<TWINT)|1<<TWEN)|(1<<TWSTO))
#define wait()   {while(!(TWCR&(1<<TWINT)));}
#define  test_ack()  (TWSR&0XF8)
#define  set_ack()   (TWSR|=(1<<TWEA))
#define  set_noack() (TWCR=(1<<TWENA))
#define  twi()    (TWCR=(1<<TWINT)|(1<<TWEN))
#define  write8bit(x) {TWDR=X; TWCR=(1<<TWINT)|(1<<TWEN);}  


uchar  table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar table2[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar disp[8]={0,0,0,0,0,0,0,0};
  void delay(int  t)//延时函数
{
int k,j;
for(k=0;k<t;k++)
for(j=0;j<10;j++);
}
  
void init (void )
{
DDRB=0XFF;   // 端口初始化
PORTB=0X00;

DDRA=0XFF;
PORTA=0;

}

void display(uchar *p)
{
      char i;
      for(i=0;i<8;i++)
      {
      PORTA=table[*p];//段选
      p++;
      PORTB=table2[i];//位选
      delay(10);
      }
}
   
void twi_init(void)
{
  TWBR=0X20;//大于10
  TWCR=0X04;//开启twi总线
  TWSR=0;//1分频
}


uchar  iic_write(uchar wadata,uchar addr)
{
  start();//开始信号
  wait();//等待
  if(teset_ack()!=START)//检验twi状态寄存器
  return 1;
  
  write8bit(WD_DEVICE_ADDR);//发送器件地址
  wait();                   //等待
  if(teset_ack()!=MT_SLA_ACK )//检验TWI 状态寄存器,屏蔽预分频位,
  //如果状态字不是MT_SLA_ACK 转出错处理
  return 1;
  
  write8bit(addr);//写地址
  wait();//等待
  if(teset_ack()!=MR_DATA_ACK  )//检验TWI 状态寄存器,屏蔽预分频器,如
//果状态字不是MT_DATA_ACK 转出错处处理
  return 1;
  
  write8bit(wadata);//写数据
  wait();//等待
  if(teset_ack()!=MR_DATA_ACK  )//检验TWI 状态寄存器,屏蔽预分频器,如
  //果状态字不是MT_DATA_ACK 转出错处处理
  return 1;
  
  stop();//停止信号
  return 0;
}
uchar iic_read(uchar addr)
{
  uchar temp;
  start();//开始信号
  wait();//等待
  if(teset_ack()!=START)//检验twi状态寄存器
  return 1;
  
  write8bit(WD_DEVICE_ADDR);//发送器件地址
  wait();                   //等待
  if(teset_ack()!=MT_SLA_ACK )//检验TWI 状态寄存器,屏蔽预分频位,
  //如果状态字不是MT_SLA_ACK 转出错处理
  return 1;
  
  write8bit(addr);//写地址
  wait();//等待
  if(teset_ack()!=MR_DATA_ACK  )//检验TWI 状态寄存器,屏蔽预分频器,如
//果状态字不是MT_DATA_ACK 转出错处处理
  return 1;
  
  start();//开始信号
  wait();//等待
  if(teset_ack()!=RE_START)//检验twi状态寄存器
  return 1;
  
  write8bit( RD_DEVICE_ADDR );//发送器件地址
  wait();                   //等待
  if(teset_ack()!=MR_SLA_ACK )//检验TWI 状态寄存器,屏蔽预分频位,
  //如果状态字不是MT_SLA_ACK 转出错处理
  return 1;
  
  twi();//重新启动
  wait();//等待
  if(teset_ack()!=MR_DATA_NOACK )//检验TWI 状态寄存器,屏蔽预分频位,
  //如果状态字不是MT_SLA_ACK 转出错处理
  return 1;
  
  temp=TWDR;
  stop()//停止信号
  return temp;
}

void main(void )
{
uchar i;
init();
twi_init();
i=iic_read(0x20);
i++;
disp[0]=i/100;
disp[1]=i%100/10;
disp[2]=i%100%10;
while (iic_write(i,0x20));
  while(1)
{
display(disp);
}


}



本帖子中包含更多资源

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

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2013-7-7 16:30:36 | 显示全部楼层
这个是编译报错的截图

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2013-7-7 16:59:58 | 显示全部楼层
1、以下代码少了左括号
#define start()  (TWCR=(1<<TWINT)|1<<TWSTA)|(1<<TWEN))
#define stop()   (TWCR=(1<<TWINT)|1<<TWEN)|(1<<TWSTO))
2、#define  write8bit(x) {TWDR=X; TWCR=(1<<TWINT)|(1<<TWEN);} // x注意大小写
3、宏定义处是#define  test_ack()  (TWSR&0XF8)    但函数中写的是teset_ack()

出0入0汤圆

发表于 2013-7-7 17:05:00 | 显示全部楼层
额,1个小时都检查不出来...给你改好了,请认真学习一下宏定义还有注意键盘打字的粘连还有分号也别漏...PS:既然用了ACC怎么还用类似于1<<TWINT的表达...
  1. //开机次数的记忆
  2. #include <iom16v.h>
  3. #include <macros.h>
  4. #define uchar  unsigned char
  5. #define uint  unsigned int
  6. //命令定义
  7. //MT 为主机发送  mr 为主机接收
  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. //前四位与器件地址有关
  19. #define   RD_DEVICE_ADDR 0XA1
  20. #define   WD_DEVICE_ADDR 0XA0

  21. //常用twi操作(主模式写和读)
  22. #define start()  (TWCR = BIT(TWINT)|BIT(TWSTA)|BIT(TWEN))
  23. #define stop()   (TWCR = BIT(TWINT)|BIT(TWSTO)|BIT(TWEN))
  24. #define wait()   {while(!(TWCR & BIT(TWINT)));}
  25. #define  teset_ack()  (TWSR & 0xf8)
  26. #define  set_ack()   (TWSR|=BIT(TWEA))
  27. #define  set_noack() (TWCR=BIT(TWEN))
  28. #define  twi()    (TWCR = BIT(TWINT)|BIT(TWEA)|BIT(TWEN))
  29. #define  write8bit(x) {TWDR = (x);TWCR = BIT(TWINT)|BIT(TWEN);}  


  30. uchar  table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  31. uchar table2[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
  32. uchar disp[8]={0,0,0,0,0,0,0,0};
  33.   void delay(int  t)//延时函数
  34. {
  35. int k,j;
  36. for(k=0;k<t;k++)
  37. for(j=0;j<10;j++);
  38. }
  39.   
  40. void init (void )
  41. {
  42. DDRB=0XFF;   // 端口初始化
  43. PORTB=0X00;

  44. DDRA=0XFF;
  45. PORTA=0;

  46. }

  47. void display(uchar *p)
  48. {
  49.       char i;
  50.       for(i=0;i<8;i++)
  51.       {
  52.       PORTA=table[*p];//段选
  53.       p++;
  54.       PORTB=table2[i];//位选
  55.       delay(10);
  56.       }
  57. }
  58.    
  59. void twi_init(void)
  60. {
  61.   TWBR=0X20;//大于10
  62.   TWCR=0X04;//开启twi总线
  63.   TWSR=0;//1分频
  64. }


  65. uchar  iic_write(uchar wadata,uchar addr)
  66. {
  67.   start();//开始信号
  68.   wait();//等待
  69.   if(teset_ack()!=START)//检验twi状态寄存器
  70.   return 1;
  71.   
  72.   write8bit(WD_DEVICE_ADDR);//发送器件地址
  73.   wait();                   //等待
  74.   if(teset_ack()!=MT_SLA_ACK )//检验TWI 状态寄存器,屏蔽预分频位,
  75.   //如果状态字不是MT_SLA_ACK 转出错处理
  76.   return 1;
  77.   
  78.   write8bit(addr);//写地址
  79.   wait();//等待
  80.   if(teset_ack()!=MR_DATA_ACK  )//检验TWI 状态寄存器,屏蔽预分频器,如
  81. //果状态字不是MT_DATA_ACK 转出错处处理
  82.   return 1;
  83.   
  84.   write8bit(wadata);//写数据
  85.   wait();//等待
  86.   if(teset_ack()!=MR_DATA_ACK  )//检验TWI 状态寄存器,屏蔽预分频器,如
  87.   //果状态字不是MT_DATA_ACK 转出错处处理
  88.   return 1;
  89.   
  90.   stop();//停止信号
  91.   return 0;
  92. }
  93. uchar iic_read(uchar addr)
  94. {
  95.   uchar temp;
  96.   start();//开始信号
  97.   wait();//等待
  98.   if(teset_ack()!=START)//检验twi状态寄存器
  99.   return 1;
  100.   
  101.   write8bit(WD_DEVICE_ADDR);//发送器件地址
  102.   wait();                   //等待
  103.   if(teset_ack()!=MT_SLA_ACK )//检验TWI 状态寄存器,屏蔽预分频位,
  104.   //如果状态字不是MT_SLA_ACK 转出错处理
  105.   return 1;
  106.   
  107.   write8bit(addr);//写地址
  108.   wait();//等待
  109.   if(teset_ack()!=MR_DATA_ACK  )//检验TWI 状态寄存器,屏蔽预分频器,如
  110. //果状态字不是MT_DATA_ACK 转出错处处理
  111.   return 1;
  112.   
  113.   start();//开始信号
  114.   wait();//等待
  115.   if(teset_ack()!=RE_START)//检验twi状态寄存器
  116.   return 1;
  117.   
  118.   write8bit( RD_DEVICE_ADDR );//发送器件地址
  119.   wait();                   //等待
  120.   if(teset_ack()!=MR_SLA_ACK )//检验TWI 状态寄存器,屏蔽预分频位,
  121.   //如果状态字不是MT_SLA_ACK 转出错处理
  122.   return 1;
  123.   
  124.   twi();//重新启动
  125.   wait();//等待
  126.   if(teset_ack()!=MR_DATA_NOACK )//检验TWI 状态寄存器,屏蔽预分频位,
  127.   //如果状态字不是MT_SLA_ACK 转出错处理
  128.   return 1;
  129.   
  130.   temp=TWDR;
  131.   stop();//停止信号
  132.   return temp;
  133. }

  134. void main(void )
  135. {
  136. uchar i;
  137. init();
  138. twi_init();
  139. i=iic_read(0x20);
  140. i++;
  141. disp[0]=i/100;
  142. disp[1]=i%100/10;
  143. disp[2]=i%100%10;
  144. while (iic_write(i,0x20));
  145.   while(1)
  146. {
  147. display(disp);
  148. }


  149. }
复制代码

出0入0汤圆

发表于 2013-7-7 17:06:25 | 显示全部楼层
richu 发表于 2013-7-7 16:59
1、以下代码少了左括号
#define start()  (TWCR=(1

还有一个stop()的调用少了分号...

出0入0汤圆

发表于 2013-7-7 17:55:41 | 显示全部楼层
这样没耐心很不好,语法错误都是可以自己处理的。

出0入0汤圆

发表于 2013-7-7 22:16:54 | 显示全部楼层
phoebuss 发表于 2013-7-7 17:06
还有一个stop()的调用少了分号...

是的,贴出来的代码少了分号,附件中的代码是有这个分号的。

出0入0汤圆

 楼主| 发表于 2013-7-8 07:52:42 | 显示全部楼层
谢谢各位的帮组,我的程序改好了,我还有个疑问,如下图红色框中所示,有的程序编译是2%full  ,有的是%3full  ,还有的%6full那个值代表了什么?怎么减小那个值

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2013-7-8 07:53:57 | 显示全部楼层
richu 发表于 2013-7-7 16:59
1、以下代码少了左括号
#define start()  (TWCR=(1

按照你的意见,程序修改好了。

出0入0汤圆

 楼主| 发表于 2013-7-8 07:55:59 | 显示全部楼层
phoebuss 发表于 2013-7-7 17:06
还有一个stop()的调用少了分号...

检查的很仔细,我改向你好好学习,我觉得你应该写过很多代码。

出0入0汤圆

 楼主| 发表于 2013-7-8 07:57:08 | 显示全部楼层
ashaohlt 发表于 2013-7-7 17:55
这样没耐心很不好,语法错误都是可以自己处理的。

嗯,看来写代码得认真点

出0入0汤圆

发表于 2013-7-8 10:55:04 | 显示全部楼层
yao2013lin 发表于 2013-7-8 07:55
检查的很仔细,我改向你好好学习,我觉得你应该写过很多代码。

我也是随便玩玩写的代码,只是错多了就会注意了...

出0入0汤圆

发表于 2013-7-8 12:46:56 | 显示全部楼层
phoebuss 发表于 2013-7-7 17:05
额,1个小时都检查不出来...给你改好了,请认真学习一下宏定义还有注意键盘打字的粘连还有分号也别漏...PS: ...

代码怎么可以贴出这种效果,记录行数

出0入0汤圆

发表于 2013-7-8 17:49:50 | 显示全部楼层
hyghyg1234 发表于 2013-7-8 12:46
代码怎么可以贴出这种效果,记录行数

点开高级回复里面有个双尖号图标就是了...
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 23:50

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表