查看: 3141|回复: 8

[原创] 扔一份SDK2.0模拟IIC驱动24C02的代码(FSL全系通用)

[复制链接]
  • TA的每日心情

    2017-1-4 08:05
  • 签到天数: 11 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    85

    主题

    1629

    帖子

    1

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    2569

    优秀版主

    最后登录
    2019-3-28
    发表于 2016-6-27 08:08:47 | 显示全部楼层 |阅读模式
    本帖最后由 技术范儿 于 2016-6-27 08:08 编辑

    最近做项目,自己整的基于SDK2.0的任意IO模拟IIC驱动,用起来就是这么任性!原理什么的都不讲了不会的百度或搜狗吧,讲的都很详细,直接上代码,成功驱动PCF8563、AT24C02以及MAX11614,喜欢的拿走吧,不谢!
    1. #include "at24c02.h"



    2. void delay_us(uint16_t xus)
    3. {
    4.     uint16_t i,j;
    5.     for(i=xus;i>0;i--)
    6.        for(j=16;j>0;j--)
    7.           __asm("NOP");
    8. }

    9. void delay_ms(uint16_t xms)
    10. {
    11.     uint16_t i,j;
    12.     for(i=xms;i>0;i--)
    13.         for(j=19999;j>0;j--)
    14.             __asm("NOP");
    15. }

    16. static void SDA_OUT()
    17. {
    18.    gpio_pin_config_t sda_config = {kGPIO_DigitalOutput, 1};
    19.    
    20.    CLOCK_EnableClock (kCLOCK_PortC);
    21.   
    22.    PORT_SetPinMux (PORTC,9U,kPORT_MuxAsGpio);//I2C0_SDA
    23.    GPIO_PinInit(GPIOC,9U,&sda_config);
    24.   
    25. }

    26. static void SDA_IN()
    27. {
    28.    gpio_pin_config_t sda_config = {kGPIO_DigitalInput, 1};
    29.    
    30.    CLOCK_EnableClock (kCLOCK_PortC);
    31.   
    32.    PORT_SetPinMux (PORTC,9U,kPORT_MuxAsGpio);//I2C0_SDA
    33.    GPIO_PinInit(GPIOC,9U,&sda_config);
    34. }
    35.   
    36. static void myiic_Config()
    37. {
    38.    gpio_pin_config_t scl_config = {kGPIO_DigitalOutput, 1};
    39.    
    40.    CLOCK_EnableClock (kCLOCK_PortC);
    41.   
    42.    PORT_SetPinMux (PORTC,8U,kPORT_MuxAsGpio);//I2C0_SCL
    43.    GPIO_PinInit(GPIOC,8U,&scl_config);
    44. }

    45. void IIC_Start(void)
    46. {
    47.         SDA_OUT();     //sda线输出
    48.         IIC0_SDA_H;//IIC_SDA=1;                    
    49.         IIC0_SCL_H;//IIC_SCL=1;
    50.         delay_us(4);
    51.          IIC0_SDA_L;//IIC_SDA=0;//START:when CLK is high,DATA change form high to low
    52.         delay_us(4);
    53.         IIC0_SCL_L;//IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
    54. }         
    55. //产生IIC停止信号
    56. void IIC_Stop(void)
    57. {
    58.         SDA_OUT();//sda线输出
    59.         IIC0_SCL_L;//IIC_SCL=0;
    60.         IIC0_SDA_L;//IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
    61.          delay_us(4);
    62.         IIC0_SCL_H;//IIC_SCL=1;
    63.         IIC0_SDA_H;//IIC_SDA=1;//发送I2C总线结束信号
    64.         delay_us(4);                                                                  
    65. }
    66. //等待应答信号到来
    67. //返回值:1,接收应答失败
    68. //        0,接收应答成功
    69. uint8_t IIC_Wait_Ack(void)
    70. {
    71.         uint8_t ucErrTime=0;
    72.         SDA_IN();      //SDA设置为输入  
    73.         IIC0_SDA_H;//IIC_SDA=1;
    74.   delay_us(1);           
    75.         IIC0_SCL_H;//IIC_SCL=1;
    76.   delay_us(1);         
    77.         while(IIC0_SDA)
    78.         {
    79.                 ucErrTime++;
    80.                 if(ucErrTime>250)
    81.                 {
    82.                         IIC_Stop();
    83.                         return 1;
    84.                 }
    85.         }
    86.         IIC0_SCL_L;//IIC_SCL=0;//时钟输出0            
    87.         return 0;  
    88. }
    89. //产生ACK应答
    90. void IIC_Ack(void)
    91. {
    92.         IIC0_SCL_L;//IIC_SCL=0;
    93.         SDA_OUT();
    94.         IIC0_SDA_L;//IIC_SDA=0;
    95.         delay_us(2);
    96.         IIC0_SCL_H;//IIC_SCL=1;
    97.         delay_us(2);
    98.         IIC0_SCL_L;//IIC_SCL=0;
    99. }
    100. //不产生ACK应答                    
    101. void IIC_NAck(void)
    102. {
    103.         IIC0_SCL_L;//IIC_SCL=0;
    104.         SDA_OUT();
    105.         IIC0_SDA_H;//IIC_SDA=1;
    106.         delay_us(2);
    107.         IIC0_SCL_H;//IIC_SCL=1;
    108.         delay_us(2);
    109.         IIC0_SCL_L;//IIC_SCL=0;
    110. }                                                                              
    111. //IIC发送一个字节
    112. //返回从机有无应答
    113. //1,有应答
    114. //0,无应答                          
    115. void IIC_Send_Byte(uint8_t txd)
    116. {                        
    117.    uint8_t t;   
    118.         SDA_OUT();            
    119.     IIC0_SCL_L;//IIC_SCL=0;//拉低时钟开始数据传输
    120.     for(t=0;t<8;t++)
    121.     {              
    122.         //IIC_SDA=(txd&0x80)>>7;
    123.                 if((txd&0x80)>>7)
    124.                         IIC0_SDA_H;//IIC_SDA=1;
    125.                 else
    126.                         IIC0_SDA_L;//IIC_SDA=0;
    127.                 txd<<=1;           
    128.                 delay_us(2);   //对TEA5767这三个延时都是必须的
    129.                 IIC0_SCL_H;//IIC_SCL=1;
    130.                 delay_us(2);
    131.                 IIC0_SCL_L;//IIC_SCL=0;        
    132.                 delay_us(2);
    133.     }         
    134. }            
    135. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
    136. uint8_t IIC_Read_Byte(unsigned char ack)
    137. {
    138.         unsigned char i,receive=0;
    139.         SDA_IN();//SDA设置为输入
    140.     for(i=0;i<8;i++ )
    141.         {
    142.         IIC0_SCL_L;//IIC_SCL=0;
    143.         delay_us(2);
    144.                     IIC0_SCL_H;//IIC_SCL=1;
    145.         receive<<=1;
    146.         if(IIC0_SDA)receive++;   
    147.                 delay_us(1);
    148.     }                                         
    149.     if (!ack)
    150.         IIC_NAck();//发送nACK
    151.     else
    152.         IIC_Ack(); //发送ACK   
    153.     return receive;
    154. }

    155. void AT24CXX_Config(void)
    156. {
    157.   myiic_Config();
    158.   SDA_OUT();
    159. }


    160. uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr)
    161. {                                 
    162.         uint8_t temp=0;                                                                                                                                                               
    163.     IIC_Start();  
    164.         if(EE_TYPE>AT24C16)
    165.         {
    166.                 IIC_Send_Byte(0xA0);           //发送写命令
    167.                 IIC_Wait_Ack();
    168.                 IIC_Send_Byte(ReadAddr>>8);//发送高地址
    169.                 IIC_Wait_Ack();                 
    170.         }else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据         

    171.         IIC_Wait_Ack();
    172.     IIC_Send_Byte(ReadAddr%256);   //发送低地址
    173.         IIC_Wait_Ack();            
    174.         IIC_Start();                     
    175.         IIC_Send_Byte(0XA1);           //进入接收模式                           
    176.         IIC_Wait_Ack();         
    177.     temp=IIC_Read_Byte(0);                  
    178.     IIC_Stop();//产生一个停止条件            
    179.         return temp;
    180. }
    181. //在AT24CXX指定地址写入一个数据
    182. //WriteAddr  :写入数据的目的地址   
    183. //DataToWrite:要写入的数据
    184. void AT24CXX_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite)
    185. {                                                                                                                                                                                          
    186.     IIC_Start();  
    187.         if(EE_TYPE>AT24C16)
    188.         {
    189.                 IIC_Send_Byte(0XA0);            //发送写命令
    190.                 IIC_Wait_Ack();
    191.                 IIC_Send_Byte(WriteAddr>>8);//发送高地址
    192.          }else
    193.         {
    194.                 IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据
    195.         }         
    196.         IIC_Wait_Ack();           
    197.     IIC_Send_Byte(WriteAddr%256);   //发送低地址
    198.         IIC_Wait_Ack();                                                                                                               
    199.         IIC_Send_Byte(DataToWrite);     //发送字节                                                           
    200.         IIC_Wait_Ack();                                 
    201.     IIC_Stop();//产生一个停止条件
    202.         delay_ms(10);         
    203. }
    204. //在AT24CXX里面的指定地址开始写入长度为Len的数据
    205. //该函数用于写入16bit或者32bit的数据.
    206. //WriteAddr  :开始写入的地址  
    207. //DataToWrite:数据数组首地址
    208. //Len        :要写入数据的长度2,4
    209. void AT24CXX_WriteLenByte(uint16_t WriteAddr,uint32_t DataToWrite,uint8_t Len)
    210. {         
    211.         uint8_t t;
    212.         for(t=0;t<Len;t++)
    213.         {
    214.                 AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
    215.         }                                                                                                   
    216. }

    217. //在AT24CXX里面的指定地址开始读出长度为Len的数据
    218. //该函数用于读出16bit或者32bit的数据.
    219. //ReadAddr   :开始读出的地址
    220. //返回值     :数据
    221. //Len        :要读出数据的长度2,4
    222. uint32_t AT24CXX_ReadLenByte(uint16_t ReadAddr,uint8_t Len)
    223. {         
    224.         uint8_t t;
    225.         uint32_t temp=0;
    226.         for(t=0;t<Len;t++)
    227.         {
    228.                 temp<<=8;
    229.                 temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);                                             
    230.         }
    231.         return temp;                                                                                                   
    232. }
    233. //检查AT24CXX是否正常
    234. //这里用了24XX的最后一个地址(255)来存储标志字.
    235. //如果用其他24C系列,这个地址要修改
    236. //返回1:检测失败
    237. //返回0:检测成功
    238. uint8_t AT24CXX_Check(void)
    239. {
    240.         uint8_t temp;
    241.         temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX                           
    242.         if(temp==0X55)return 0;                  
    243.         else//排除第一次初始化的情况
    244.         {
    245.                 AT24CXX_WriteOneByte(255,0X55);
    246.           temp=AT24CXX_ReadOneByte(255);         
    247.                 if(temp==0X55)return 0;
    248.         }
    249.         return 1;                                                                                          
    250. }

    251. //在AT24CXX里面的指定地址开始读出指定个数的数据
    252. //ReadAddr :开始读出的地址 对24c02为0~255
    253. //pBuffer  :数据数组首地址
    254. //NumToRead:要读出数据的个数
    255. void AT24CXX_Read(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
    256. {
    257.         while(NumToRead)
    258.         {
    259.                 *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);        
    260.                 NumToRead--;
    261.         }
    262. }  
    263. //在AT24CXX里面的指定地址开始写入指定个数的数据
    264. //WriteAddr :开始写入的地址 对24c02为0~255
    265. //pBuffer   :数据数组首地址
    266. //NumToWrite:要写入数据的个数
    267. void AT24CXX_Write(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)
    268. {
    269.         while(NumToWrite--)
    270.         {
    271.                 AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
    272.                 WriteAddr++;
    273.                 pBuffer++;
    274.         }
    275. }
    复制代码
    1. #ifndef __AT24C02_H
    2. #define __AT24C02_H

    3. #include "fsl_common.h"
    4. #include "fsl_port.h"
    5. #include "clock_config.h"
    6. #include "fsl_gpio.h"

    7. #define H 1
    8. #define L 0
    9. #define IIC0_GPIO GPIOC
    10. #define IIC0_SDA_Pin  9
    11. #define IIC0_SCL_Pin  8

    12. #define IIC0_SDA_H   GPIO_WritePinOutput(IIC0_GPIO,IIC0_SDA_Pin,H)
    13. #define IIC0_SDA_L   GPIO_WritePinOutput(IIC0_GPIO,IIC0_SDA_Pin,L)
    14. #define IIC0_SCL_H   GPIO_WritePinOutput(IIC0_GPIO,IIC0_SCL_Pin,H)
    15. #define IIC0_SCL_L   GPIO_WritePinOutput(IIC0_GPIO,IIC0_SCL_Pin,L)
    16. #define IIC0_SDA     GPIO_ReadPinInput(IIC0_GPIO,IIC0_SDA_Pin)


    17. #define IIC_Adder 0xA0

    18. #define AT24C01                127
    19. #define AT24C02                255
    20. #define AT24C04                511
    21. #define AT24C08                1023
    22. #define AT24C16                2047
    23. #define AT24C32                4095
    24. #define AT24C64            8191
    25. #define AT24C128        16383
    26. #define AT24C256        32767  
    27. //定义EE_TYPE为AT24C02
    28. #define EE_TYPE AT24C02

    29. void delay_us(uint16_t xus);
    30. void delay_ms(uint16_t xms);
    31. void IIC_Start(void);
    32. void IIC_Stop(void);
    33. uint8_t IIC_Wait_Ack(void);
    34. void IIC_Ack(void);
    35. void IIC_NAck(void);
    36. void IIC_Send_Byte(uint8_t txd);
    37. uint8_t IIC_Read_Byte(unsigned char ack);

    38. uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr);                                                        //指定地址读取一个字节
    39. void AT24CXX_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite);                //指定地址写入一个字节
    40. void AT24CXX_WriteLenByte(uint16_t WriteAddr,uint32_t DataToWrite,uint8_t Len);//指定地址开始写入指定长度的数据
    41. uint32_t AT24CXX_ReadLenByte(uint16_t ReadAddr,uint8_t Len);                                        //指定地址开始读取指定长度数据
    42. void AT24CXX_Write(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite);        //从指定地址开始写入指定长度的数据
    43. void AT24CXX_Read(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead);           //从指定地址开始读出指定长度的数据

    44. uint8_t AT24CXX_Check(void);  //检查器件
    45. void AT24CXX_Config(void);

    46. #endif
    复制代码


    回复

    使用道具 举报

    该用户从未签到

    2

    主题

    43

    帖子

    0

    注册会员

    Rank: 2

    积分
    94
    最后登录
    2018-5-11
    发表于 2016-6-27 09:40:04 | 显示全部楼层
    好东西 感谢分享
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    5

    主题

    22

    帖子

    0

    注册会员

    Rank: 2

    积分
    55
    最后登录
    2018-5-28
    发表于 2016-6-27 09:40:10 | 显示全部楼层
    感谢分享
    回复

    使用道具 举报

    该用户从未签到

    10

    主题

    34

    帖子

    0

    注册会员

    Rank: 2

    积分
    88
    最后登录
    2018-6-27
    发表于 2016-6-27 09:44:32 | 显示全部楼层
    感谢分享
    回复

    使用道具 举报

    该用户从未签到

    6

    主题

    26

    帖子

    0

    注册会员

    Rank: 2

    积分
    64
    最后登录
    2018-5-3
    发表于 2016-6-27 09:44:39 | 显示全部楼层
    感谢分享
    回复

    使用道具 举报

    该用户从未签到

    9

    主题

    15

    帖子

    0

    新手上路

    Rank: 1

    积分
    45
    最后登录
    2018-5-8
    发表于 2016-6-27 09:44:48 | 显示全部楼层
    感谢分享
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2020-4-26 22:12
  • 签到天数: 586 天

    连续签到: 1 天

    [LV.9]以坛为家II

    1

    主题

    1620

    帖子

    6

    金牌会员

    Rank: 6Rank: 6

    积分
    3240
    最后登录
    2020-4-26
    发表于 2016-6-27 10:40:02 | 显示全部楼层
    感谢分享
    2020加油
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-9-13 10:15
  • 签到天数: 35 天

    连续签到: 1 天

    [LV.5]常住居民I

    13

    主题

    500

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1183
    最后登录
    2024-12-10
    发表于 2016-6-27 11:04:16 | 显示全部楼层
    感谢分享
    回复

    使用道具 举报

    该用户从未签到

    712

    主题

    6371

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    24864
    最后登录
    2025-7-18
    发表于 2016-6-27 14:00:35 | 显示全部楼层
    感谢楼主的资料分享!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-19 06:42 , Processed in 0.102441 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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