打印

【连载】STM8L051F3_09_IIC应用

[复制链接]
1196|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
caijie001|  楼主 | 2018-5-24 17:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本文介绍STM8L051F3的IIC相关知识。内容分为以下几部分:
  • IIC简介
  • OLED显示
1、IIC基础知识IIC(Inter-integrated circuit):集成电路总线。STM8L051F3的IIC拥有提供多主机功能,可以控制特定的IIC总线序列、协议、仲裁和时间管理,支持标准和快速模式,可用于各种应用上,如CRC生成和验证、SMBus(系统管理总线)和PMBus(电源管理总线),使用DMA功能可以减少CPU的负荷。STM8L051F3的IIC主要特点如下:
  • 并行总线/IIC协议转换器
  • 多主机功能:同一个接口可作为主机或从机
  • IIC主机特点:
    • 时钟生成
    • 起始和停止条件生成
  • IIC从机特点:
    • 可编程的IIC地址检测
    • 停止位检测
    • IIC双重寻址能力,可拥有两个2个IIC地址
  • 7位/10位和一般呼叫地址生成和检测
  • 支持不同的通讯速度:
    • 标准速度(100kHz)
    • 快速(400kHz)
  • 状态标志:
    • 发送和接收模式标志
    • 发送字节结束标志
    • IIC忙标志
  • 错误标志:
    • 主模式仲裁条件丢失
    • 在地址/数据发送后应答失败
    • 检测到错误的起始或停止条件
    • 禁止时钟延展的Overrun/underrun
  • 三种类型中断
    • 通讯中断
    • 错误条件中断
    • 从停机模式下唤醒中断
  • 唤醒功能:
    • 在从机模式下通过地址检测可将MCU从低功耗模式唤醒
  • 可选择的时钟延展
  • 在DMA功能下的1字节缓冲器
  • 可配置的PEC(数据表错误检测)产生或验证:
    • PEC的值能在发送模式下作为最后一个字节发送
    • 在接收到的最后一个字节PEC错误检测
  • 兼容SMBus2.0
    • 25ms时钟拉低超时延迟
    • 10ms主机积累时钟拉低延展时间
    • 25ms从机积累时钟拉低延展时间
    • 硬件PEC生成/验证和应答控制
    • 支持地址分辨协议(ARP)
  • PMBus 能力
STM8L051F3的IIC能运行在从机发送、从机接收、主机发送和主机接收四中模式,在默认的情况下工作在从机模式,当产生一个起始条件后,会自动地从从机模式转换为主机模式。IIC模块的框图如下:


STM8L051F3的IIC功能很多,在本章主要介绍常用的主机模式下的发送与接收功能。IIC的输入时钟(系统时钟)在标准模式下要大于1MHz,在快速模式下要大于4MHz。
主机模式下的发送序列如下图:



主模式下的读模式会根据读不同数据大小有不通的程序序列,在IIC用于中断的模式下并拥有高的中断优先级时,读序列如下:


主模式接收的数据N > 2时(N为字节数),读序列如下:


主模式接收的数据N = 2时(N为字节数),读序列如下:


主模式接收的数据N = 1时(N为字节数),读序列如下:


说明:
S = 起始条件,Sr =重复起始条件,P=停止条件,A=应答,NA=不应答
EVX=事件x
EV5:SB=1,读SR1寄存器清除,之后接着往DR寄存器写入地址
EV6:ADDR=1,读SR1寄存器清除,之后接着读SR3
EV6_1:没有相关的标志事件,应答在EV6后应该禁止,这是在ADDRS被清除后发生
EV6_3:ADDR=1,编程ACK=0,在读SR1寄存器后清除接着读SR3寄存器编程STOP=1
EV7:RXNE=1,读DR寄存器清除
EV7_1:RXNE=1,读DR寄存器清除,编程ACK=0和STOP请求
EV7_2:BTF=1,第N-2个数据在DR寄存器,第N-1个数据在转移寄存器,编程ACK=0,在 DR寄存器中读出第N-2个数据,编程STOP=1,读出第N-1个数据
EV7_3:BTF=1,编程STOP=1后连续读DR寄存器两次
EV8_1:转移寄存器空,数据寄存器空,写DR寄存器
EV8:TXE=1,转移寄存器非空,数据寄存器空,写DR寄存器清除
EV8_2:TXE=1,BTF=1,编程停止条件请求,在硬件产生停止条件后自动清除
EV9:ADD10=1,读SR1寄存器清除,接着写DR寄存器
IIC在主模式的通讯中就是严格按照上述的序列进行通讯,理解了每个事件的含义对理解上述IIC通讯的序列有很大帮助。STM8L051F3的编程采用的是官方库函数,相对来说较为容易。
2、OLED显示2.1 IIC配置本小节介绍如何初始化IIC以及实现IIC与OLED进行通讯。OLED采用的是技新0.96寸OLED(4PIN),可以直接插入核心板P6接口。本次实验设计的内容为:点亮0.96’OLED屏,使用OLED显示‘OLED TEST’ 字符串,同时LED1闪烁。使用的例程:STM8L051F3_09_IIC。IIC初始化配置步骤:
1)打开IIC外设时钟
2)使能IIC1
3)配置IIC参数:IIC1、时钟100KHz、IIC模式、快速模式工作周期Tlow/Thigh = 2、使能应答、应答从机地址7位
本章所使用例程主要在于IIC外设的应用,OLED使用的是技新0.96寸OLED(4PIN),相关内容在这里不介绍,用户可以通过技新的0.96'OLED(4Pin)学习手册来了解OLED相关的设计原理与程序应用。同时要注意的是:OLED的IIC通讯地址是0x78、OLED的IIC时序只存在写,不存在读。
OLED的通讯时序如下:


2.2 例程介绍IIC初始化函数在例程的iic.c文件中实现:
void IIC_Init(void)
{
  //打开IIC外设时钟
  CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE);
  I2C_Cmd(I2C1, ENABLE);     //使能IIC外设
  /* 配置IIC参数 */
  I2C_Init(I2C1, 100000, 0x78, I2C_Mode_I2C, I2C_DutyCycle_2,
           I2C_Ack_Enable, I2C_AcknowledgedAddress_7bit);
}
根据OLED的时序,通过IIC协议对OLED写入命令函数如下(在oled.c文件中实现):
void Write_OLED_Command(unsigned char IIC_Command)
{
  //检测总线忙
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
  //产生IIC起始条件
  I2C_GenerateSTART(I2C1, ENABLE);
  //检测IIC的EV5
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
  //发送从机器件地址
  I2C_Send7bitAddress(I2C1, 0x78, I2C_Direction_Transmitter);
  //检测IIC的EV6
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  //发送数据(命令)
  I2C_SendData(I2C1, 0x00);
  //检测IIC的EV8
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  // 发送命令
  I2C_SendData(I2C1, IIC_Command);
  //检测IIC的EV8
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  //产生停止条件
  I2C_GenerateSTOP(I2C1, ENABLE);
}
根据OLED的时序,通过IIC协议对OLED写入数据函数如下(在oled.c文件中实现):
void Write_OLED_Data(unsigned char IIC_Data)
{
  //检测总线忙
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
  //产生IIC起始条件
  I2C_GenerateSTART(I2C1, ENABLE);
  //检测IIC的EV5
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
  //发送从机器件地址
  I2C_Send7bitAddress(I2C1, 0x78, I2C_Direction_Transmitter);
  //检测IIC的EV6
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  //发送数据(命令)
  I2C_SendData(I2C1, 0x40);
  //检测IIC的EV8
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  // 发送命令
  I2C_SendData(I2C1, IIC_Data);
  //检测IIC的EV8
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  //产生停止条件
  I2C_GenerateSTOP(I2C1, ENABLE);
}
最后主函数如下:
void main(void)
{
  LED_Init();   //初始化LED
  IIC_Init();   //IIC初始化
  OLED_Init();  //OLED初始化
  OLED_Clear(); //OLED清屏
  OLED_ShowString(30,0,"OLED TEST");    //显示 OELD TEST
while(1)
{
    delay_ms(300);
    GPIO_ToggleBits(LED1_GPIO_PORT, LED1_GPIO_PINS); //切换LED1状态
}
}
使用ST-LINK把程序下载到开发板,LED1闪烁,OLED显示:OLED TEST。注:对于移植OLED的例程,主需要针对OLED写入数据&写入命令两个函数即可,其他的不需要改动。效果如下:



相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:21ic公开课专区:http://open.21ic.com/ 21ic资料下载中心:http://dl.21ic.com/ 21ic项目外包中心:http://project.21ic.com/ 杰杰欢迎大家有空常来赛事专区逛逛

131

主题

3790

帖子

63

粉丝