[Cortex-M0技术交流] 【第7帖】I2C硬件程序实现

[复制链接]
4027|7
 楼主| nixianmin 发表于 2011-11-13 07:35 | 显示全部楼层 |阅读模式
本帖最后由 nixianmin 于 2011-11-13 07:37 编辑

好久没发帖子了,前段时间学了下LOOK,现在又回来用库函数试试。参考坛里的I2C帖子写了个I2C,调试成功。刚开始看官方例子,无从下手,后来参考多了,才开始下手,无非就是在I2C的中断里通过status状态码判断,并根据参考手册上的I2C数据传输模式的图来判断。我这个程序就是实现简单的I2C操作,用中断断点来看读取的数据,写的有点不好,只是实现罢了。

main.c

  1. /*********************************************
  2. //
  3. //
  4. **********************************************/
  5. #include<stdio.h>
  6. #include"NUC1xx.h"
  7. #include"M0Base.h"
  8. #include"DrvGPIO.h"
  9. #include"M0Uart.h"
  10. #include"M0Timer.h"
  11. #include"lcd1602.h"
  12. #include"m0rtc.h"
  13. #include"M0I2c.h"

  14. int main(void)
  15. {

  16.   UNLOCKREG();   //解寄存器锁保护
  17.   PLL50M();
  18.   LOCKREG();
  19.   i2c_tr_buf[0]='0';
  20.   i2c_tr_buf[1]='1';
  21.   i2c_tr_buf[2]='2';
  22.   i2c_tr_buf[3]='3';
  23.   i2c_tr_buf[4]='4';

  24.   InitUart0();
  25.   InitTimer0();
  26.   InitLcd1602();
  27.   InitRtc();
  28.   InitI2c_Master();
  29.   Set_I2c_Start(0xa0,I2C_WRITE,10,0x0000);
  30.   Set_I2c_Start(0xa0,I2C_WRITE,0,0x0002);           //不写数据,只写存储地址,和读数据一起用
  31.   Set_I2c_Start(0xa0,I2C_READ,5,0x00);//这里地址不起作用

  32.   while(1)
  33.   {
  34.          
  35.   }
  36. }




m0i2c.h
  1. /*********************************************
  2. //
  3. //
  4. **********************************************/
  5. #ifndef _M0I2C_H_
  6. #define _M0I2C_H_

  7. #define I2C_READ  1
  8. #define I2C_WRITE  0

  9. extern uint8_t i2c_tr_buf[],i2c_re_buf[];
  10. extern uint8_t i2c_flag;

  11. void InitI2c_Master(void);

  12. void Set_I2c_Start(int8_t ssalve,int8_t srw,int8_t snum,int16_t sadd);

  13. #endif




m0i2c.c
  1. /*********************************************
  2. //
  3. //
  4. **********************************************/
  5. #include"stdio.h"
  6. #include"NUC1xx.h"
  7. #include"DrvI2C.H"
  8. #include"DrvGPIO.H"
  9. #include"DrvSYS.h"
  10. #include"m0i2c.h"

  11. uint8_t i2c_tr_buf[10]={0};
  12. uint8_t        i2c_re_buf[10]={0};
  13. uint8_t i2c_flag=0;

  14. typedef struct{
  15.         int8_t i2c_salve;        //传输从机地址
  16.         int8_t i2c_rw;
  17.         int8_t dat_num;                //传输数据个数
  18.         int8_t dat_cnt;                //传输数据数据计数
  19.         int16_t dat_add;   //传输数据的其实地址

  20. }I2C_TYPE;

  21. volatile I2C_TYPE i2c={0,0,0,0};
  22. //地址对读数据无效
  23. //读数据只能先写地址,再读数据
  24. void Set_I2c_Start(int8_t ssalve,int8_t srw,int8_t snum,int16_t sadd)
  25. {
  26.         uint16_t cnt=0;
  27.         i2c.i2c_salve=ssalve;
  28.         i2c.i2c_rw=srw;
  29.         i2c.dat_num=snum;
  30.         i2c.dat_cnt=0;
  31.         i2c.dat_add=sadd;
  32.         i2c_flag=0 ;

  33.         DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0);
  34.         while((i2c_flag!=1)&&(cnt!=0xffff))
  35.                 cnt++;//判断是否读取或写结束
  36.         DrvSYS_Delay(8000);//延时
  37. }

  38. void I2c1CallBack(uint32_t status)
  39. {
  40.         if(i2c.i2c_rw==I2C_READ)  //读状态
  41.         {
  42.                 if (status == 0x08)                     /* START has been transmitted and prepare SLA+W */
  43.             {
  44.                 DrvI2C_WriteData(I2C_PORT1, (i2c.i2c_salve|0x01));         //读地址数据
  45.                 DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  46.             }  
  47.             else if (status == 0x40)                /* SLA+R has been transmitted and ACK has been received */
  48.             {
  49.                 DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);          //have ack
  50.             }      
  51.                 else if(status==0x50)
  52.                 {
  53.                          i2c_re_buf[i2c.dat_cnt++] = DrvI2C_ReadData(I2C_PORT1);
  54.                         if(i2c.dat_cnt<(i2c.dat_num-1))
  55.                         {
  56.                         DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
  57.                         }
  58.                         else
  59.                         {
  60.                                 DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  61.                         }
  62.                
  63.                 }
  64.             else if (status == 0x58)                /* DATA has been received and NACK has been returned */
  65.             {
  66.                 i2c_re_buf[i2c.dat_cnt++] = DrvI2C_ReadData(I2C_PORT1);
  67.                 DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);
  68.                         i2c_flag=1;
  69.             }
  70.             else
  71.             {
  72.                 printf("Status 0x%x is NOT processed\n", status);
  73.             }  
  74.        
  75.         }
  76.         else if(i2c.i2c_rw==I2C_WRITE)   //写状态
  77.         {
  78.                 if (status == 0x08)                     /* START has been transmitted */
  79.             {
  80.                 DrvI2C_WriteData(I2C_PORT1, (i2c.i2c_salve&0xfe));         //读地址数据
  81.                 DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  82.             }   
  83.             else if (status == 0x18)                /* SLA+W has been transmitted and ACK has been received */
  84.             {
  85.                 DrvI2C_WriteData(I2C_PORT1, (int8_t)(i2c.dat_add));         //传输高位地址
  86.                         i2c.dat_cnt++;
  87.                 DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  88.             }
  89.             else if (status == 0x20)                /* SLA+W has been transmitted and NACK has been received */
  90.             {
  91.                 
  92.                 DrvI2C_Ctrl(I2C_PORT1, 1, 1, 1, 0);
  93.             }   
  94.             else if (status == 0x28)                /* DATA has been transmitted and ACK has been received */
  95.             {
  96.                 if (i2c.dat_cnt<2)
  97.                 {
  98.                     DrvI2C_WriteData(I2C_PORT1, (int8_t)(i2c.dat_add>>8));//传输低位地址
  99.                                 i2c.dat_cnt++;
  100.                     DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  101.                 }
  102.                         else if(i2c.dat_cnt<(i2c.dat_num+2))
  103.                         {
  104.                                  DrvI2C_WriteData(I2C_PORT1, i2c_tr_buf[i2c.dat_cnt-2]);
  105.                                 i2c.dat_cnt++;
  106.                     DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
  107.                         }
  108.                 else
  109.                 {
  110.                     DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);//send a stop
  111.                                 i2c_flag=1;
  112.                 }        
  113.             }
  114.             else
  115.             {
  116.                 printf("Status 0x%x is NOT processed\n", status);
  117.             }
  118.        
  119.         }
  120. }

  121. void InitI2c_Master()
  122. {
  123.         DrvGPIO_InitFunction(E_FUNC_I2C1);
  124.         DrvI2C_Open(I2C_PORT1, 50000);
  125.         DrvI2C_EnableInt(I2C_PORT1);
  126.         DrvI2C_InstallCallback(I2C_PORT1, I2CFUNC, I2c1CallBack);
  127. }

本帖子中包含更多资源

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

×
hotpower 发表于 2011-11-13 09:27 | 显示全部楼层
库函数的套路就是先初始化设置并安装回调函数。然后启动硬件开始。在回调函数处理或设置标志在主循环中处理。iic接线简单,但比spi要复杂些。
 楼主| nixianmin 发表于 2011-11-13 12:15 | 显示全部楼层
2# hotpower 如果只控制些I2C总线的器件,用模拟方式比较简单,
硬件的麻烦,我以前写430用硬件愣是没搞出来,只好用模拟方式
hotpower 发表于 2011-11-13 12:23 | 显示全部楼层
晕,模拟要占用大量的时间资源
chy117 发表于 2011-11-13 22:09 | 显示全部楼层
yuandm1 发表于 2011-11-13 22:18 | 显示全部楼层
继续学习
xinxi 发表于 2011-11-13 23:30 | 显示全部楼层
占用2个中断,88条指令汇编实现i2c从模式,100k 速度,不怎么占用系统资源,因为中断处理时间 很短 很短,没有长时间独占cpu,,,如果搞成 一检测到开始标志,cpu就全部用来接收i2c数据,其它事情不能做,一直到检测到结束标志或者出错才释放cpu占用,那就没意思了哦
hotpower 发表于 2011-11-14 09:59 | 显示全部楼层
回调函数类似与事件或消息驱动机制。
当中断来后,在中断中先查看用户回调是否安装。
即回调函数指针是否为空。非空即有用户回调,
要特别注意此回调函数实际还是运行在中断服务程序之中的,不要处理过长时间。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:电机控制,TI InstaSpin Foc交流群:335663930

40

主题

431

帖子

6

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