找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3379|回复: 1
收起左侧

AVR单片机的TWI中断模式

[复制链接]
ID:282997 发表于 2018-2-8 09:43 | 显示全部楼层 |阅读模式
使用AVR单片机内部的TWI功能,并采用中断工作模式,可以很好的使用Atmega系列的内部资源,并提高程序的稳定性;
  1. #include <BCD.h>

  2. unsigned char i2c_sla;
  3. unsigned char i2c_addrh,i2c_addrl;
  4. unsigned char i2c_wr;
  5. unsigned char i2c_sub_flag;
  6. unsigned char i2c_num;
  7. unsigned char *i2c_buf;
  8. unsigned char i2c_end;

  9. /***********************************************************************************************************************************************************************
  10. 函数名称:interrupt [TWI] void twi_isr(void)
  11. 函数功能:i2c底层中断处理函数(时钟SD2201和AT24C256共同的)
  12. ***********************************************************************************************************************************************************************/
  13. interrupt [TWI] void twi_isr(void)
  14. {

  15.      unsigned char i2c_sta,tmp = 0;
  16.      i2c_sta = TWSR;
  17.      switch(i2c_sta)
  18.      {
  19.           case 0x08:
  20.                    if(i2c_sub_flag == 1)
  21.                    {
  22.                         TWDR = i2c_sla&0xfe;
  23.                    }
  24.                    else
  25.                    {
  26.                         TWDR = i2c_sla;
  27.                    }
  28.                    //TWCR &= 0xcf;
  29.                    //TWCR |= 0x80;
  30.                    TWCR = 0x85;
  31.                    break;
  32.           case 0x10:
  33.                    TWDR = i2c_sla;
  34.                    //TWCR &= 0xcf;
  35.                    //TWCR |= 0x80;
  36.                    TWCR = 0x85;
  37.                    //i2c_sub_flag = 1;
  38.                    break;
  39.           case 0x18:
  40.                    if(i2c_sub_flag == 0)
  41.                    {
  42.                         if(i2c_num > 0)
  43.                         {
  44.                              TWDR = *i2c_buf;
  45.                              //TWCR &= 0xcf;
  46.                              //TWCR |= 0x80;
  47.                              TWCR = 0x85;
  48.                              i2c_buf++;
  49.                              i2c_num--;
  50.                         }
  51.                         else
  52.                         {
  53.                              //TWCR &= 0xdf;
  54.                              //TWCR |= 0x90;
  55.                              TWCR = 0x95;
  56.                              i2c_end = 1;
  57.                         }
  58.                    }
  59.                    if(i2c_sub_flag == 1)
  60.                    {
  61.                         TWDR = i2c_addrh;
  62.                         //TWCR &= 0xcf;
  63.                         //TWCR |= 0x80;
  64.                         TWCR = 0x85;
  65.                         i2c_sub_flag = 2;
  66.                    }
  67.                    break;
  68.           case 0x28:
  69.                    if(i2c_sub_flag == 3)
  70.                    {
  71.                         if(i2c_wr == 0)
  72.                         {
  73.                              if(i2c_num > 0)
  74.                              {
  75.                                  
  76.                                   TWDR = *i2c_buf;
  77.                                   i2c_buf++;
  78.                                   //TWCR &= 0xcf;
  79.                                   //TWCR |= 0x80;
  80.                                   TWCR = 0x85;
  81.                                   i2c_num--;
  82.                              }
  83.                              else
  84.                              {
  85.                                   //TWCR &= 0xdf;
  86.                                   //TWCR |= 0x90;
  87.                                   TWCR = 0x95;
  88.                                   i2c_end = 1;
  89.                              }
  90.                         }
  91.                    }
  92.                    if(i2c_sub_flag == 2)
  93.                    {
  94.                         TWDR = i2c_addrl;
  95.                         //TWCR &= 0xcf;
  96.                         //TWCR |= 0x80;
  97.                         TWCR = 0x85;
  98.                         i2c_sub_flag = 3;
  99.                    }
  100.                   
  101.                    if(i2c_sub_flag == 3)
  102.                    {
  103.                         if(i2c_wr == 1)
  104.                         {
  105.                              //TWCR &= 0xef;
  106.                              //TWCR |= 0xa0;
  107.                              TWCR = 0xa5;
  108.                         }
  109.                    }
  110.                    if(i2c_sub_flag == 0)
  111.                    {
  112.                         if(i2c_num > 0)
  113.                         {
  114.                              TWDR = *i2c_buf;
  115.                              //TWCR &= 0xcf;
  116.                              //TWCR |= 0x80;
  117.                              TWCR = 0x85;
  118.                              i2c_buf++;
  119.                              i2c_num--;
  120.                         }
  121.                         else
  122.                         {
  123.                              //TWCR &= 0xdf;
  124.                              //TWCR |= 0x90;
  125.                              TWCR = 0x95;
  126.                              i2c_end = 1;
  127.                         }
  128.                    }
  129.                    break;
  130.           case 0x20:
  131.           case 0x30:
  132.           case 0x48:
  133.                    i2c_end = 0xff;
  134.                    //TWCR &= 0xfe;
  135.                    break;
  136.           case 0x38:
  137.                    TWCR &= 0xed;
  138.                    TWCR |= 0xa4;
  139.                    i2c_end = 0xfe;
  140.                    //TWCR &= 0xfe;
  141.                    break;
  142.           case 0x40:
  143.                    //TWCR &= 0xcf;
  144.                    //TWCR |= 0xc0;
  145.                    TWCR = 0xc5;
  146.                    break;
  147.           case 0x50:
  148.                    *i2c_buf = TWDR;
  149.                    i2c_buf++;
  150.                    i2c_num--;
  151.                    if(i2c_num == 0)
  152.                    {
  153.                         //TWCR &= 0x8f;
  154.                         //TWCR |= 0x80;
  155.                         TWCR = 0x85;
  156.                    }
  157.                    else
  158.                    {
  159.                         //TWCR &= 0xcf;
  160.                         //TWCR |= 0xc0;
  161.                         TWCR = 0xc5;
  162.                    }
  163.                    break;
  164.           case 0x58:
  165.                    tmp = TWDR;
  166.                    //TWCR &= 0xdf;
  167.                    //TWCR |= 0x90;
  168.                    TWCR = 0x95;
  169.                    i2c_end = 1;
  170.                    break;
  171.           default:
  172.                   TWCR &= 0xfe;
  173.                   break;
  174.      }
  175. }
  176. /***********************************************************************************************************************************************************************
  177. 函数名称:void tran_dat(unsigned char *a,unsigned char num,unsigned char fx)
  178. 函数功能:i2c传输数据是由MSB开始LSB结束,而SD2201的数据传输是由LSB开始MSB结束,此函数负责数据做此转换的
  179. 函数参数:unsigned char *a  数据的启始指针,
  180.            unsigned char num 数据的字节个数
  181.            unsigned char fx  时钟写和读的标志位, 1-写,0-读
  182. ***********************************************************************************************************************************************************************/
  183. void tran_dat(unsigned char *a,unsigned char num,unsigned char fx)
  184. {
  185.      unsigned char j,k,dat;
  186.      for(j = 0;j < num;j++)
  187.      {
  188.           dat = *a;
  189.           if(fx == 1)
  190.           {
  191.                *a = bin2bcd(dat);
  192.           }
  193.          
  194.           dat = *a;
  195.           *a = 0;
  196.           *a |= dat & 0x01;  
  197.           for(k = 1;k < 8;k++)
  198.           {
  199.                *a <<= 1;
  200.                dat >>= 1;
  201.                *a |= dat & 0x01;
  202.           }
  203.           dat = *a;
  204.           if(fx == 0)
  205.           {
  206.                if((j == 4)&&(num == 7))
  207.                {
  208.                     dat &= 0x3f;
  209.                }
  210.                if((j == 0)&&(num == 3))
  211.                {
  212.                     dat &= 0x3f;
  213.                }
  214.                *a = bcd2bin(dat);
  215.           }
  216.           a++;
  217.      }
  218. }
  219. /***********************************************************************************************************************************************************************
  220. 函数名称:unsigned char i2c_w_n(unsigned char sla,unsigned char *s,unsigned char num)
  221. 函数功能:无子地址写入N字节数据
  222. 函数参数:unsigned char sla  器件地址
  223.            unsigned char *s   写入数据缓冲区指针
  224.            unsigned char num  写入数据个数  
  225. ***********************************************************************************************************************************************************************/
  226. unsigned char i2c_w_n(unsigned char sla,unsigned char *s,unsigned char num)
  227. {
  228.      i2c_sla =  sla;
  229.      i2c_buf = s;
  230.      i2c_num = num;
  231.      i2c_sub_flag = 0;
  232.      i2c_end = 0;
  233.      TWCR=0xa5;
  234.      while(i2c_end == 0);
  235.      if(i2c_end == 1)
  236.      {
  237.           delay_ms(10);
  238.           return(1);
  239.      }
  240.      else
  241.      {
  242.           return(0);
  243.      }
  244. }
  245. /***********************************************************************************************************************************************************************
  246. 函数名称:unsigned char i2c_rec_n(unsigned char sla,unsigned char *s,unsigned char num)
  247. 函数功能:无子地址读出N字节数据
  248. 函数参数:unsigned char sla  器件地址
  249.            unsigned char *s   读出数据缓冲区指针
  250.            unsigned char num  读出数据个数
  251. ***********************************************************************************************************************************************************************/
  252. unsigned char i2c_rec_n(unsigned char sla,unsigned char *s,unsigned char num)
  253. {
  254.      i2c_sla =  sla + 1;
  255.      i2c_buf = s;
  256.      i2c_num = num;
  257.      i2c_sub_flag = 0;
  258.      i2c_end = 0;
  259.      TWCR=0xa5;
  260.      while(i2c_end == 0);
  261.      if(i2c_end == 1)
  262.      {
  263.           return(1);
  264.      }
  265.      else
  266.      {
  267.           return(0);
  268.      }
  269.      
  270. }
  271. /***********************************************************************************************************************************************************************
  272. 函数名称:unsigned char i2c_w_subn(unsigned char sla,unsigned char ah,unsigned char al,unsigned char *s,unsigned char num)
  273. 函数功能:有子地址写入N字节数据
  274. 函数参数:unsigned char sla  器件地址
  275.            unsigned char ah   器件子地址高字节
  276.            unsigned char al   器件子地址低字节
  277.            unsigned char *s   写入数据缓冲区指针
  278.            unsigned char num  写入数据个数  
  279. ***********************************************************************************************************************************************************************/
  280. unsigned char i2c_w_subn(unsigned char sla,unsigned char ah,unsigned char al,unsigned char *s,unsigned char num)
  281. {
  282.      i2c_sla =  sla;
  283.      i2c_buf = s;
  284.      i2c_num = num;
  285.      i2c_addrh = ah;
  286.      i2c_addrl = al;
  287.      i2c_wr = 0;
  288.      i2c_sub_flag = 1;
  289.      i2c_end = 0;
  290.      TWCR=0xa5;
  291.      while(i2c_end == 0);
  292.      if(i2c_end == 1)
  293.      {
  294.           delay_ms(10);
  295.           return(1);
  296.      }
  297.      else
  298.      {
  299.           return(0);
  300.      }
  301. }
  302. /***********************************************************************************************************************************************************************
  303. 函数名称:unsigned char i2c_rec_subn(unsigned char sla,unsigned char ah,unsigned char al,unsigned char *s,unsigned char num)
  304. 函数功能:无子地址读出N字节数据
  305. 函数参数:unsigned char sla  器件地址
  306.            unsigned char ah   器件子地址高字节
  307.            unsigned char al   器件子地址低字节
  308.            unsigned char *s   读出数据缓冲区指针
  309.            unsigned char num  读出数据个数
  310. ***********************************************************************************************************************************************************************/
  311. unsigned char i2c_rec_subn(unsigned char sla,unsigned char ah,unsigned char al,unsigned char *s,unsigned char num)
  312. {
  313.      i2c_sla =  sla + 1;
  314.      i2c_buf = s;
  315.      i2c_num = num;
  316.      i2c_addrh = ah;
  317.      i2c_addrl = al;
  318.      i2c_wr = 1;
  319.      i2c_sub_flag = 1;
  320.      i2c_end = 0;
  321.      TWCR=0xa5;
  322.      while(i2c_end == 0);
  323.      if(i2c_end == 1)
  324.      {
  325.           return(1);
  326.      }
  327.      else
  328.      {
  329.           return(0);
  330.      }
  331. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:259979 发表于 2018-3-11 06:48 来自手机 | 显示全部楼层
谢谢分享代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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