查看: 3418|回复: 0

[原创] 【IRD-LPC1768-DEV】IIC

[复制链接]
  • TA的每日心情
    无聊
    2021-12-29 19:06
  • 签到天数: 47 天

    连续签到: 1 天

    [LV.5]常住居民I

    49

    主题

    188

    帖子

    21

    金牌会员

    Rank: 6Rank: 6

    积分
    1392
    最后登录
    2025-3-4
    发表于 2019-3-10 11:57:45 | 显示全部楼层 |阅读模式
    本帖最后由 day_day 于 2019-3-10 14:15 编辑

    老实说这是挺久之前弄的了,这个星期为找工作的事情焦头烂额,现在抽空来天下坑,有些地方记得不太清楚了……
    (一)IIC初始化配置

    主要寄存器:
    @GV9S`}[8ODWHJ7EX[SP[P5.png
    主要有三步:使能电源、时钟,配置引脚复用,配置IIC,如果需要中断还要配置中断
    1. void I2cInit(void)
    2. {
    3.         //1、使能电源、时钟(略,默认配置)
    4.    LPC_SYSCTL->PCONP        |=  0x00000080;
    5.         //2、配置引脚复用
    6.    LPC_IOCON->PINSEL[1]  |=  0x01400000;
    7.         //3、配置IIC
    8.         //3.1-清除标志位
    9.    LPC_I2C0->CONCLR =  I2CONSET_AA | I2CONSET_SI | I2CONSET_STA | I2CONSET_I2EN;
    10.         //3.2-配置高低电平占空比
    11.    LPC_I2C0->SCLL   =  0x80;
    12.    LPC_I2C0->SCLH   =  0x80;
    13.         //3.3-使能
    14.    LPC_I2C0->CONSET =  I2CONSET_I2EN;
    15.    LPC_I2C0->CONSET =  I2CONSET_STO;
    16. }
    复制代码


    (二)IIC发送
    根绝数据手册,主发送模式:

    1、
    必须置位I2EN来使能I2C功能。如果AA位为 0,而另一个器件成为总线的主控制器时,I2C接口不会对任何地址产生应答,也就是说它无法进入从模式。

    首先我们需要置位EN来使能IIC,但由于其默认值为1,已经使能,所以可以不配置。
    但AA位必须配置为0才能防止进入从模式!

    2、
    通过软件置位 STA,将进入 I2C 主发送模式。I2C 逻辑在总线空闲后立即发送一个起始条件。当发送完起始条件后,SI 会置位。此时 I2STAT 中的状态代码为 0x08。该状态代码用于中断服务程序的处理。该中断程序把从地址和写操作位装入 I2DAT(数据寄存器),然后清零 SI位。向 I2CONCLR 寄存器中的 SIC 位写入 1 可清零 SI。

    可以看到,主发送模式下I2C的起始条件是:置位STA!
    但同时还要注意到,SI在发送完成会置位,为了区分发送完成和发送未完成,必须事先清除SI!

    3、
    LPC1768的IIC设计艺术是将之分为三个部分的:
    开头起始部分、中间发送部分、末尾结束部分

    4、开头起始部分
    通过软件置位 STA,将进入 I 2 C 主发送模式。I 2 C 逻辑在总线空闲后立即发送一个起始条件。当发送完起始条件后,SI 会置位。此时 I2STAT 中的状态代码为 0x08。该状态代码用于中断服务程序的处理。

    即置位STA产生其实条件后,SI会置位,我们通过阻塞实现:
    1. LPC_I2C0->CONCLR =  I2CONSET_AA | I2CONSET_SI | I2CONSET_STA | I2CONSET_STO;
    2.   LPC_I2C0->CONSET =  I2CONSET_STA | I2CONSET_I2EN;
    3.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for START
    复制代码


    5、末尾结束部分
    在主模式中,当 STO 为 1 时,会使 I 2 C 接口发送一个停止条件或在从模式中从错误状态中恢复。当主模式中 STO=1 时,向 I 2 C 总线发送停止条件。当总线检测到停止条件时,STO 自动清零。

    通过置位STO控制位,产生结束条件。然后阻塞访问知道STO又变成0
    1. LPC_I2C0->CONSET =  I2CONSET_STO;
    2.   LPC_I2C0->CONCLR =  I2CONSET_SI;
    3.   while (LPC_I2C0->CONSET & I2CONSET_STO);
    复制代码


    6、中间发送部分
    把从地址和写操作位装入 I2DAT(数据寄存器),然后清零 SI位。向 I2CONCLR 寄存器中的 SIC 位写入 1 可清零 SI。

    数据手册里面建议在中断里面装载DAT,我们先阻塞装载:
    1.         
    2.         LPC_I2C0->DAT    =  hwaddr;
    3.   LPC_I2C0->CONCLR =  I2CONSET_SI | I2CONSET_STA;
    4.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for ADDRESS send
    5.   
    6.   LPC_I2C0->DAT    =  command;
    7.   LPC_I2C0->CONCLR =  I2CONSET_SI;
    8.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for DATA send
    9.   
    10.   LPC_I2C0->DAT    =  data;
    11.   LPC_I2C0->CONCLR =  I2CONSET_SI;
    12.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for DATA send
    13.   
    复制代码
    这是常见的三段式IIC通讯。

    (三)IIC接收
    接收会稍微麻烦些,数据手册写得很暧昧不清,让人无法捉摸发送和接收之间如何切换。实际上它这里提到这么一句:

    1. 发送完重复的起始条件之后,I 2 C 可以切换到主发送模式。
    复制代码
    那么也就是说,重复起始条件同样也能从主发送切换到主接收?
    当 STA=1 并且 I 2 C 接口还没进入主模式时,I 2 C 接口进入主模式,检测总线并在总线空闲时产生一个起始条件。如果总线忙,则等待一个停止条件(释放总线)并在延迟半个内部时钟发生器周期后发送一个起始条件。当 I 2 C 接口已经处于主模式中并发送或接收了数据时,I 2 C 接口会发送一个重复的起始条件。STA 可在任何时候置位,当 I 2 C 接口处于可寻址的从模式时,STA 也可以置位。

    那么就是说STA已经为1的时候再往STA里面写1就能进入重复发送条件?
    1. unsigned char IICReadChar(unsigned char hwaddr, unsigned char command)
    2. {
    3.         unsigned char rec;
    4.         
    5.         LPC_I2C0->CONCLR =  I2CONSET_AA | I2CONSET_SI | I2CONSET_STA | I2CONSET_STO;
    6.   LPC_I2C0->CONSET =  I2CONSET_STA | I2CONSET_I2EN;
    7.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for START
    8.         
    9.         LPC_I2C0->DAT    =  hwaddr;
    10.   LPC_I2C0->CONCLR =  I2CONSET_SI | I2CONSET_STA;
    11.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for ADDRESS(write) send
    12.   
    13.   LPC_I2C0->DAT    =  command;
    14.   LPC_I2C0->CONCLR =  I2CONSET_SI;
    15.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for DATA(ass_addr) send
    16.   
    17.         LPC_I2C0->CONCLR =  I2CONSET_AA | I2CONSET_SI | I2CONSET_STA | I2CONSET_STO;
    18.   LPC_I2C0->CONSET =  I2CONSET_STA | I2CONSET_I2EN;
    19.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));                                //restart

    20.         LPC_I2C0->DAT    =  hwaddr+0x01;
    21.   LPC_I2C0->CONCLR =  I2CONSET_SI | I2CONSET_STA;
    22.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for ADDRESS(read) send
    23.   
    24.   //LPC_I2C0->I2DAT    =  data;
    25.   LPC_I2C0->CONCLR =  I2CONSET_SI;
    26.   while (!(LPC_I2C0->CONSET & I2CONSET_SI));        // Wait for DATA send
    27.   rec = LPC_I2C0->DAT;
    28.         
    29.   LPC_I2C0->CONSET =  I2CONSET_STO;
    30.   LPC_I2C0->CONCLR =  I2CONSET_SI;
    31.   while (LPC_I2C0->CONSET & I2CONSET_STO);                                        //end
    32.         
    33.         return rec;
    34. }
    复制代码
    测试了一下,果然如此

    (四)IIC实战
    板子左下角的四个led就是由一个IIC设备控制,其IIC地址为0xC0,其0x06地址里面每两位控制一个led灯,00为低电平,01为高电平,LED另一端接3.3V,即低电平亮!

    IICSendChar(0xC0, 0x06, 0x54);

    灯就亮起来了!



    该会员没有填写今日想说内容.
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-7-20 20:11 , Processed in 0.081964 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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