找回密码
 立即注册

QQ登录

只需一步,快速开始

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

stm8用IIC读写24c02源程序

[复制链接]
ID:170809 发表于 2017-3-15 09:06 | 显示全部楼层 |阅读模式
给大家分享一个 stm8单片机用IIC总线方式读写24c02存储芯片 里面是自己写的程序
0.png
完整源码下载:
4.I2C 24C02.rar (396.59 KB, 下载次数: 85)


下面是部分文件预览:
  1. #include"i2c.h"

  2. uint8_t receive[N],send[N];             //全局数组变量

  3. void I2C_Start()       //发送起始信号——在SCL为高电平期间,SDA由高拉低
  4. {
  5.   SDA_OUT;
  6.   SDA_1;
  7.   SCL_1;
  8.   Delay_us(3);
  9.   SDA_0;
  10.   Delay_us(5);
  11.   SCL_0;
  12.   Delay_us(1);  
  13. }

  14. void I2C_Stop()          //结束信号——在SCL为高电平期间,SDA由低拉高
  15. {
  16.    SDA_OUT;
  17.    SDA_0;
  18.    SCL_0;
  19.    Delay_us(1);
  20.    SCL_1;
  21.    Delay_us(3);
  22.    SDA_1;
  23.    Delay_us(5);
  24.    SCL_0;  
  25.    Delay_us(1);
  26. }

  27. void I2C_Ack()            //检测应答——第9个时钟周期时,由24C16将SDA拉低
  28. {
  29.   SDA_1;
  30.   Delay_us(3);
  31.   SDA_IN;
  32.   Delay_us(1);
  33.   SCL_1;
  34.   Delay_us(2);
  35.   SCL_0;
  36.   Delay_us(3);
  37. }
  38. uint8_t I2C_Ack2()          //检测应答2
  39. {

  40.   SDA_1;
  41.   Delay_us(3);
  42.   SDA_IN;
  43.   Delay_us(2);  
  44.   SCL_1;
  45.   Delay_us(2);

  46. //  while(SDA);             //很快能完成应答,不需要等待,防止硬件故障导致出错
  47.   SCL_0;
  48.   Delay_us(2);
  49.   return SDA;
  50. }


  51. uint8_t I2C_Send(uint8_t buffer)           //发送1个字节的数据
  52. {
  53.   uint8_t temp = 0;
  54.   uint8_t BitCnt = 7;
  55.   
  56.   SDA_OUT;             //SDA为输出
  57.   Delay_us(1);
  58.   if((buffer&0x80)==0)    //由高位开始发送
  59.     SDA_0;
  60.   else
  61.     SDA_1;
  62.   Delay_us(1);
  63.   SCL_1;
  64.   Delay_us(1);
  65.   temp = buffer<<1;
  66.   buffer = temp;
  67.   while(BitCnt)
  68.   {
  69.     if((buffer&0x80)==0)
  70.     {
  71.       SCL_0;
  72.       SDA_0;
  73.     }
  74.     else
  75.     {
  76.       SCL_0;
  77.       SDA_1;
  78.     }
  79.     Delay_us(3);
  80.     SCL_1;
  81.     Delay_us(2);
  82.     temp = buffer<<1;
  83.     buffer = temp;
  84.     BitCnt--;
  85.   }
  86.   SCL_0;  
  87.   if(I2C_Ack2())           //发送8位数据后,检测应答 0:无应答 1:有应答   
  88.     return 0;
  89.   else
  90.     return 1;  
  91. }


  92. uint8_t I2C_Receive()             //接收一个字节的数据
  93. {
  94.   uint8_t ReceiveData,i;
  95.   SDA_IN;               //SDA为输入
  96.   Delay_us(1);
  97.   for(i=0;i<8;i++)      //SCL高电平时,记录SDA,由高位开始
  98.   {
  99.     SCL_1;
  100.     Delay_us(2);        //延时的时间
  101.     if(SDA==0)
  102.       ReceiveData &= 0xfe;
  103.     else
  104.       ReceiveData |= 0x01;
  105.     if(i<7)
  106.       ReceiveData = ReceiveData<<1;

  107.     SCL_0;
  108.     Delay_us(1);
  109.   }
  110.   return ReceiveData;
  111. }

  112. void I2C_NoAck()                //接收数据后不发送应答
  113. {
  114.   SDA_1;
  115.   SDA_OUT;
  116.   SDA_1;
  117.   Delay_us(1);
  118.   SCL_1;
  119.   Delay_us(2);
  120.   SCL_0;
  121.   Delay_us(2);
  122.   SDA_0;
  123.   Delay_us(2);
  124. }

  125. void I2C_SendAck()              //接收数据后发送应答,由主机发送,告知24C16已经接收到一个字节的数据
  126. {
  127.   SDA_OUT;
  128.   SDA_0;
  129.   Delay_us(1);
  130.   SCL_1;
  131.   Delay_us(3);
  132.   SCL_0;
  133.   SDA_0;
  134.   Delay_us(2);
  135. }

  136. void I2C_Write_Byte(uint8_t addr,uint8_t data)       //向24C06写入数据——单字节写
  137. {                                                                  

  138.     I2C_Start();                                //起始信号
  139.     I2C_Send(0xa0);                             //发送器件地址
  140.     I2C_Send(addr);                             //发送字节地址
  141.     I2C_Send(data);                             //发送数据
  142.     I2C_Stop();                                 //结束信号
  143. }

  144. void I2C_Write_Page(uint8_t addr,uint8_t data)       //向24C06写入数据——页写 16个字节
  145. {                                                                  
  146.   uint8_t i,j,k,p;
  147.   
  148.   if((N/16)==0)                 //判断N是否小于16 是:一次页写即可完成   否:需要多次页写
  149.   {
  150.       I2C_Start();                              //起始信号
  151.       I2C_Send(0xa0);                           //发送器件地址
  152.       I2C_Send(addr);                           //发送字节地址
  153.       for(j=0;j<N;j++)
  154.       {  
  155.         send[j] = data+j;
  156.         I2C_Send(send[j]);                      //发送数据      
  157.       }
  158.       I2C_Stop();                               //结束信号     
  159.       Delay_ms(5);
  160.   }
  161.   else                                          //多次页写
  162.   {
  163.     for(i=0;i<(N/16);i++)                       //i次页写
  164.     {
  165.       I2C_Start();                              //起始信号
  166.       I2C_Send(0xa0);                           //发送器件地址
  167.       I2C_Send(addr+i*16);                      //发送字节地址
  168.       for(j=0;j<16;j++)
  169.       {  
  170.         send[i*16+j] = data+i*16+j;
  171.         I2C_Send(send[i*16+j]);                 //发送数据      
  172.       }
  173.       I2C_Stop();                               //结束信号  
  174.       Delay_ms(5);
  175.     }
  176.    
  177.     if(N%16)                                    //写剩余的数据
  178.     {
  179.       p=N-(N%16);
  180.       I2C_Start();                              //起始信号
  181.       I2C_Send(0xa0);                           //发送器件地址   
  182.       I2C_Send(addr+p);                         //发送字节地址
  183.       for(k=0;k<(N%16);k++)  
  184.       {  
  185.         send[i*16+k] = data+i*16+k;
  186.         I2C_Send(send[i*16+k]);                 //发送数据      
  187.       }
  188.       I2C_Stop();                               //结束信号
  189.       Delay_ms(5);
  190.     }
  191.   }
  192. }


  193. void I2C_Read2(uint8_t add_start)//连续读
  194. {
  195.   uint8_t i;
  196.   
  197.   I2C_Start();                  //起始信号
  198.   I2C_Send(0xa0);               //发送器件地址——写
  199.   I2C_Send(add_start);          //发送字节地址
  200.   I2C_Start();                  //起始信号
  201.   I2C_Send(0xa1);               //发送器件地址——读
  202.   for(i=0;i<N-1;i++)
  203.   {  
  204.     receive[i]=I2C_Receive();
  205.     I2C_SendAck();              //主机发送应答,继续读
  206.   }
  207.   receive[i]=I2C_Receive();
  208.   I2C_NoAck();                  //第九个周期发送不应答
  209.   I2C_Stop();                   //停止信号
  210. // return receive;
  211. }


  212. uint8_t I2C_Read(uint8_t addr)                  //从24C06读出数据  
  213. {
  214.   uint8_t receive;
  215.   I2C_Start();                  //起始信号
  216.   I2C_Send(0xa0);               //发送器件地址——写
  217.   I2C_Send(addr);               //发送字节地址
  218.   I2C_Start();                  //起始信号
  219.   I2C_Send(0xa1);               //发送器件地址——读
  220.   receive=I2C_Receive();        //读出数据
  221.   I2C_Stop();                 //停止信号,结束读数据操作
  222.   return receive;
  223. }  

  224. void I2C_Ack_Check()          //应答查询
  225. {
  226.   I2C_Start();
  227.   I2C_Send(0xa0);
  228.   I2C_Ack2();
  229. }

  230. /*
  231. void test_1(uint8_t add,uint8_t data)     //单次测试
  232. {
  233.   uint8_t test=0;
  234.   I2C_Write_Byte(add,data);
  235.   Delay_ms(5);
  236.   test = I2C_Read(add);

  237.   if(test==data)
  238.     LED = LED1;
  239.   else
  240.     LED = LED2;
  241. }

  242. void test_write(uint8_t add,uint8_t data)     //测试_写
  243. {
  244.   
  245.   I2C_Write_Byte(add,data);
  246.   Delay_ms(5);
  247. }  
  248. uint8_t test_read(uint8_t add)                //测试_读
  249. {
  250.   uint8_t test=0;
  251.   test = I2C_Read(add);
  252.   return test;
  253. }

  254. void test1(uint8_t add_start)                  //测试函数1  
  255. {
  256.   uint8_t read[N]={0},write[N]={0},i,k=0;
  257.   
  258.   for(i=0;i<N;i++)
  259.   {
  260.     write[i]=0x02+i;
  261.     test_write(add_start+i,write[i]);
  262.   }
  263.   
  264.   for(i=0;i<N;i++)
  265.   {
  266.     read[i]=test_read(add_start+i);
  267.   }
  268.   for(i=0;i<N;i++)
  269.   {
  270.     if(write[i]==read[i])
  271.       k+=1;
  272.   }
  273.   if(k==N)
  274.     LED = LED1;
  275.   else
  276.     LED = LED2;
  277. }
  278. */
  279. void test2(uint8_t add_start,uint8_t data)                  //测试函数2  
  280. {
  281.   uint8_t i,k=0;
  282.   I2C_Write_Page(add_start,data);
  283.   I2C_Read2(add_start);
  284.   for(i=0;i<N;i++)
  285.   {
  286.     if(receive[i]==send[i])
  287.       k+=1;
  288.   }
  289.   if(k==N)
  290.     LED = LED1;
  291.   else
  292.     LED = LED2;
  293.   for(i=0;i<N;i++)
  294.   {
  295.     receive[i]=0;
  296.     send[i]=0;
  297.   }
  298.   
  299. }


  300. #pragma vector=5                //PA口的中断服务函数
  301. __interrupt void PORTA_IRQHandler(void)
  302. {
  303.   Delay_ms(20);                 //软件消抖
  304.   if(!(PA_IDR&0x04))
  305.   {
  306.     Delay_ms(20);
  307.     while(!(PA_IDR&0x04));

  308.     test2(0x00,0x06);
  309.   }
  310. }
复制代码


回复

使用道具 举报

ID:99174 发表于 2017-3-23 19:26 | 显示全部楼层
建议,延时加长,数据手册上说的是4.7us. 应答信号要加防出错标志,不等直接过,大批量的生产就会出问题
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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