一 stm32硬件IIC
硬件IIC特性架构
①通讯引脚
查看对应开发板芯片的原理图可以查看对应IIC外设引脚的位置
这里代码采用的是stm32f103c8t6,硬件IIC的外设引脚为PB6 PB7,故之后的代码中配置PB6 PB7引脚即可
②时钟控制逻辑
时钟控制寄存器CCR,数据手册中有CCR寄存器的模式选择以及快速模式下的占空比选择
计算时钟频率公式:
标准模式 Thigh = CCR x Tpclk1
Tlow = CCR x Tpclk1
快速模式 Thigh = CCR x Tpclk1
Tlow = 2 x CCR x Tpclk1 (DUTY=0)
Thigh = 9 x CCR x Tpclk1
Tlow = 16 x CCR x Tpclk1 (DUTY=1)
例如:配置200kbit/s 即 T = 1/200 000 s(DUTY=0的条件下)
CCR = Thigh/Tpclk1 = 1/200 000 / 3 * 36 000 000 = 60 (APB1系统时钟频率36MHZ)
③数据控制
IIC的SDA信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、PEC寄存器以及SDA数据线。(具体参考上面关于IIC硬件架构图片)
·当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过SDA信号线发送出去。
·当从外部接收数据的时候,数据移位寄存器把SDA信号线采样到的数据一位一位地存储到”数据寄存器”中。
以7位主发送器为例
Ev事件的寄存器可以到手册上查找对应状态寄存器下面的具体内容
过程大致描述为:发送起始信号,等待Ev5事件,Ev5 = 1,代表起始信号发送完毕
发送接收地址,等待Ev6事件,Ev6 = 1,代表接收地址相匹配
匹配完地址后就是等待Ev8_1事件到来, 这个事件代表移位寄存器为空,可以移动数据到下一位
移动到下一位地址之后就是数据的发送以及等待事件Ev8,循环往复等待数据全部发送完毕,产生EV8_2事件,SR1的TEX位及BTF位被置1,表示通讯结束。
二 OLED屏幕原理以及显示过程
0.96寸oled屏幕(采用IIC通讯)如下所示
0.96寸的oled又叫12864显示屏,分辨率为128*64(这么多个像素点),由128列,64行组成,其中64行又被分为8页,每页8行!
oled屏幕驱动指令
例如:设置开启OLED屏幕根据表中指令可以分3步
①开启显示 0xAF
②电荷泵设置 0x8D
③开启电荷泵 0x14
oled显示
这里显示第一列第一页前5个点 即为0x1f(这里是写入数据,前面的0x1f是写入命令),写完这个数据之后控制器自动移到第二列以相同的方式显示点。不能一次性控制一个点阵,只能一次性控制八位点阵,即一列点阵。这决定了字模选择的取模方式为“列行式“
三 硬件IIC相关代码
oled.c文件(包含配置OLED和硬件IIC)
#include "oled.h"
#include "stm32f10x.h"
#include "codetab.h" //字库头文件
void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_initstruct; //配置GPIO口结构体 -PB6 -PB7
I2C_InitTypeDef I2C_initstruct; //配置硬件IIC结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //使能对应时钟
//PB6 SCL PB7 SDA
GPIO_initstruct.GPIO_Mode = GPIO_Mode_AF_OD; //复用开漏
GPIO_initstruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_initstruct);
I2C_DeInit(I2C1);
I2C_initstruct.I2C_Ack =I2C_Ack_Enable; //IIC应答信号使能
I2C_initstruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //设置从机地址长度为7位
I2C_initstruct.I2C_ClockSpeed = 400000; //设置目标周期 400khz
I2C_initstruct.I2C_DutyCycle = I2C_DutyCycle_2; //设置占空比为2:1
I2C_initstruct.I2C_Mode = I2C_Mode_I2C; //设置为IIC模式
I2C_initstruct.I2C_OwnAddress1 = 0x30; //设置主机地址
I2C_Init(I2C1, &I2C_initstruct);
I2C_Cmd(I2C1, ENABLE);
}
//IIC写字节函数
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
//传参数,代表地址和数据
while(I2C_GetFlagStatus( I2C1,I2C_FLAG_BUSY)); //等待总线空闲
I2C_GenerateSTART(I2C1,ENABLE); //IIC发送起始信号
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//等待EV5=1,具体可以参考手册上面EV5事件
I2C_Send7bitAddress(I2C1, OLED_Address, I2C_Direction_Transmitter);//发送从机7位地址
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//等待EV6=1