实现效果图
I2C协议简介I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备(那些电平转化芯片),现在被广泛地使用在系统内多个集成电路(IC)间的通讯。 I2C只有一根数据总线 SDA(Serial Data Line),串行数据总线,只能一位一位的发送数据,属于串行通信,采用半双工通信 半双工通信:可以实现双向的通信,但不能在两个方向上同时进行,必须轮流交替进行,其实也可以理解成一种可以切换方向的单工通信,同一时刻必须只能一个方向传输,只需一根数据线.
对于I2C通讯协议把它分为物理层和协议层物理层规定通讯系统中具有机械、电子功能部分的特性(硬件部分),确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准(软件层面)。
I2C物理层I2C 通讯设备之间的常用连接方式
(1) 它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。 (2) 一个 I2C 总线只使用两条总线线路,一条双向串行数据线SDA(Serial Data Line ),一条串行时钟线SCL(Serial Data Line )。数据线即用来表示数据,时钟线用于数据收发同步 (3) 总线通过上拉电阻接到电源。当 I2C 设备空闲时会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。 I2C通信时单片机GPIO口必须设置为开漏输出,否则可能会造成短路。
AHT10温湿度传感器介绍AHT10是一款国产的温湿度传感器芯片,价格便宜,精度还高,体积也小。 AHT10配有一个全新设计的ASIC专用芯片、一个经过改进的MEMS半导体电容式湿度传感元件和一个标准的片上温度传感元件,其性能已经大大提升甚至超出了前一代传感器的可靠性水平,新一代温湿度传感器,经过改进使其在恶劣环境下的性能更稳定。
浏览数据手册可以得到一个大概信息: 温度范围:-40℃~85℃ 温度误差:±0.3℃ 湿度范围:0%~100% 湿度误差:±2% 工作电压:1.8v~3.6v 通讯方式:I2C 时钟频率:100kHz和400kHz
温湿度设备地址和读写命令在实际的使用过程中,AHT10的设备地址需要与读写数据/命令方向位组成一个字节同时发送,字节的最低位为读写数据/命令方向位,高7位是AHT10的设备地址。 如果要通过I2C写数据或命令给AHT10,在I2C起始信号之后,需要发送“0111 0000”,即0x70给AHT10,除了通过高7位“0111 000”的设备地址寻址还通过最低位“0”通知AHT10接下来是写数据或命令操作。 如果要通过I2C读取AHT10中的数据,在I2C起始信号之后,需要发送“0111 0001”,即0x71给AHT10,除了通过高7位“0111 000”的设备地址寻址还通过最低位“1”通知AHT10接下来是读取数据的操作。
简单来说就是,0x70表示写数据,0x71表示读数据。不过使用STM32硬件I2C时只需要输入0x70就行,最低位标准库会处理的。
读取温湿度数据
从数据手册可知,一个测量周期包概括三个步骤: 总结如下: 发送测量命令:先发送写入指令(0x70),再发送触发测量指令(0xAC),再发送命令参数(0x33和0x00)。 等待测量完成:数据手册上写的75ms,等待的时间大于这个就行了。 接收数据:发送读取指令(0x71),连续接收6个字节数据。接收到的第一个字节是状态字,检查状态字第3位校准使能位是否为1,不为1就发送初始化命令,检查第7位忙闲指示,如果是0为测量完成,进行下一步。 对接收到的数据进行转换处理。
数据的计算由AHT10数据手册可知
例如:采集到的湿度数值是0x0C6501,换算成十进制是812289。
则:湿度 = 812289 * 100 / 1048576 = 77.46 (单位:%)
采集到的温度数值是0x056A00,换算成十进制是354816。
则:温度 = ( 354816 * 200 / 1048576 ) - 50= 17.67 (单位:℃)
程序这里就放出main.c、AHT10.c和OLED.c这三个主要的代码,其他的请下载下面链接的压缩包。
AHT10和OLED模块的 SCL接PB6,SDA接PB7。
main.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "IWDG.h"
- #include "AHT10.h"
- uint16_t numlen(uint16_t num);
- int main(void)
- {
- IWDG_Configuration(); //初始化看门狗
- OLED_Init(); //初始化OLED屏
- AHT10_Init(); //初始化AHT10
-
- OLED_ShowString(1, 1, "T:");
- OLED_ShowString(2, 1, "H:");
- uint32_t a=0;
- uint16_t err_count=0;
-
- while (1)
- {
- a++;
- OLED_ShowNum(3, 1, a, 9);//计数显示,方便观察程序是否正常运行
- if(a==999999999)a=0;
- float Temp,Hum; //声明变量存放温湿度数据
-
- /*
- https://blog.zeruns.tech
- */
- if(ReadAHT10(&Hum,&Temp)) //读取温湿度数据
- {
- if(Temp>=0)
- {
- char String[10];
- sprintf(String, "+%.2fC", Temp);//格式化字符串输出到字符串变量
- OLED_ShowString(1, 3, String); //显示温度
- sprintf(String, " %.2f%%", Hum);//格式化字符串输出到字符串变量
- OLED_ShowString(2, 3, String); //显示湿度
- }else
- {
- char String[10];
- sprintf(String, "-%.2fC", Temp);//格式化字符串输出到字符串变量
- OLED_ShowString(1, 3, String); //显示温度
-
- sprintf(String, " %.2f%%", Hum);//格式化字符串输出到字符串变量
- OLED_ShowString(2, 3, String); //显示湿度
- }
- }
- else
- {
- err_count++;
- OLED_ShowNum(4,1, err_count, 5); //显示错误次数计数
- }
- Delay_ms(100); //延时100毫秒
- IWDG_FeedDog(); //喂狗(看门狗,超过1秒没有执行喂狗则自动复位)
- }
- }
复制代码
AHT10.c - #include "stm32f10x.h"
- #include "Delay.h"
- #include "OLED.h"
- /*AHT10地址*/
- #define AHT10_ADDRESS 0x38<<1 //从机地址是7位,最后一位是传输方向位,所以左移一位
- /*设置使用哪一个I2C*/
- #define I2Cx I2C1
- /*
- https://blog.zeruns.tech
- */
- /*发送起始信号*/
- void AHT10_I2C_START(){
- while( I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));//等待总线空闲
- I2C_GenerateSTART(I2Cx, ENABLE);//发送起始信号
- while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT)==ERROR);//检测EV5事件
- }
- /*发送停止信号*/
- void AHT10_I2C_STOP(){
- I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
- }
- /**
- * @brief 发送3个字节数据
- * @param cmd 命令字节
- * @param DATA0 第0个参数
- * @param DATA1 第1个参数
- * @retval 无
- */
- void AHT10_WriteByte(uint8_t cmd, uint8_t DATA0, uint8_t DATA1)
- {
- AHT10_I2C_START(); //发送起始信号
-
- I2C_Send7bitAddress(I2Cx, AHT10_ADDRESS, I2C_Direction_Transmitter); //发送设备写地址
- while(I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR); //检测EV6事件
- I2C_SendData(I2Cx, cmd);//发送命令
- while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
- I2C_SendData(I2Cx, DATA0);//发送命令参数高8位数据
- while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
-
- I2C_SendData(I2Cx, DATA1);//发送命令参数低8位数据
- while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
-
- I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
- }
- /**
- * @brief 发送命令读取AHT10的状态
- * @retval 读取到的状态字节
- */
- /*uint8_t AHT10_ReadStatus(void){
- AHT10_I2C_START();//发送起始信号
- I2C_Send7bitAddress(I2Cx,AHT10_ADDRESS,I2C_Direction_Receiver);//发送设备读地址
- while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR);//检测EV6事件
- while (!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_RECEIVED));//检测EV7事件
- I2C_AcknowledgeConfig(I2Cx, DISABLE); //关闭应答信号
- uint8_t status = I2C_ReceiveData(I2Cx);//读取数据并返回
- AHT10_I2C_STOP(); //发送停止信号
- I2C_AcknowledgeConfig(I2Cx,ENABLE);//重新开启应答信号
- return status;
- }*/
- /**
- * @brief 读取数据
- * @retval 读取到的字节数据
- */
- uint8_t AHT10_ReadData(void)
- {
- while (!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_RECEIVED));//检测EV7事件
- return I2C_ReceiveData(I2Cx);//读取数据并返回
- }
- /*软件复位AHT10*/
- void AHT10_SoftReset(void)
- {
- AHT10_I2C_START(); //发送起始信号
- I2C_Send7bitAddress(I2Cx, AHT10_ADDRESS, I2C_Direction_Transmitter); //发送设备写地址
- while(I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR); //检测EV6事件
- I2C_SendData(I2Cx, 0xBA);//发送软复位命令
- while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
- I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
- Delay_ms(20);
- }
- /*引脚初始化*/
- void AHT10_Init(void)
- {
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); //使能I2C1时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
-
- /*STM32F103芯片的硬件I2C1: PB6 -- SCL; PB7 -- SDA */
- GPIO_InitTypeDef GPIO_InitStructure; //定义结构体配置GPIO
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //设置输出模式为开漏输出,需接上拉电阻
- GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIO
-
- I2C_DeInit(I2Cx); //将外设I2C寄存器重设为缺省值
- I2C_InitTypeDef I2C_InitStructure; //定义结构体配置I2C
- I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //工作模式
- I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //时钟占空比,Tlow/Thigh = 2
- I2C_InitStructure.I2C_OwnAddress1 = 0x88; //主机的I2C地址,用不到则随便写,无影响
- I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能应答位
- I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//设置地址长度7位
- I2C_InitStructure.I2C_ClockSpeed = 400000; //I2C传输速度,400K,根据自己所用芯片手册查看支持的速度。
- I2C_Init(I2Cx, &I2C_InitStructure); //初始化I2C
- I2C_Cmd(I2Cx, ENABLE); //启用I2C
- Delay_ms(20);//上电延时
- AHT10_WriteByte(0XE1,0X08,0x00);//发送指令初始化
- Delay_ms(20);
- }
- /**
- * @brief 读取AHT10数据
- * @param *Hum 湿度
- * @param *Temp 温度
- * @retval 1 - 读取成功;0 - 读取失败
- */
- uint8_t ReadAHT10(float *Hum,float *Temp)
- {
- uint8_t Data[5];//声明变量存放读取的数据
- AHT10_WriteByte(0XAC,0X33,0x00);//发送指令触发测量
- Delay_ms(70); //延时70毫秒等待测量完成
- AHT10_I2C_START();//发送起始信号
- I2C_Send7bitAddress(I2Cx,AHT10_ADDRESS,I2C_Direction_Receiver);//发送设备读地址
- while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR);//检测EV6事件
-
- uint8_t i;
- for(i=0;i<6;i++)//循环6次读取6个字节数据
- {
- if (i == 5) //读取最后1个字节时关闭应答信号
- {
- I2C_AcknowledgeConfig(I2Cx, DISABLE); //关闭应答信号
- }
- Data[i] = AHT10_ReadData(); //读取数据
- if (i == 5)
- I2C_GenerateSTOP(I2Cx, ENABLE); //发送停止信号
- }
- I2C_AcknowledgeConfig(I2Cx,ENABLE);//重新开启应答信号
- if( (Data[0]&0x08) == 0 )//0x08(00001000)检查状态字节第3位(校准使能位)是否为0
- {
- AHT10_WriteByte(0XE1,0X08,0x00); //发送指令初始化
- Delay_ms(20);
- return 0;
- }
- else if( (Data[0]&0x80) == 0 )//0x80(10000000)检查状态字节第7位(忙闲指示)是否为0
- {
-
- uint32_t SRH = (Data[1]<<12) | (Data[2]<<4) | (Data[3]>>4); //湿度数据处理
- uint32_t ST = ((Data[3]&0x0f)<<16) | (Data[4]<<8) | Data[5];//温度数据处理
- *Hum = (SRH * 100.0) / 1024.0 / 1024; //根据手册给的公式转换湿度数据
- *Temp = (ST * 200.0) / 1024.0 / 1024 - 50; //根据手册给的公式转换温度数据
- return 1;
- }
- I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
- return 0;
- }
- /*
- https://blog.zeruns.tech
- */
复制代码
OLED.c - #include "stm32f10x.h"
- #include "OLED_Font.h"
- /*OLED屏地址*/
- #define OLED_ADDRESS 0x78
- /*设置哪一个使用I2C*/
- #define I2Cx I2C1
- /*
- https://blog.zeruns.tech
- */
- /*引脚初始化*/
- void OLED_I2C_Init(void)
- {
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); //使能I2C1时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
-
- /*STM32F103芯片的硬件I2C: PB6 -- SCL; PB7 -- SDA */
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //设置输出模式为开漏输出,需接上拉电阻
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- I2C_DeInit(I2Cx); //将外设I2C寄存器重设为缺省值
- I2C_InitTypeDef I2C_InitStructure;
- I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //工作模式
- I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //时钟占空比,Tlow/Thigh = 2
- I2C_InitStructure.I2C_OwnAddress1 = 0x88; //主机的I2C地址,用不到则随便写,无影响
- I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能应答位
- I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//设置地址长度7位
- I2C_InitStructure.I2C_ClockSpeed = 400000; //I2C传输速度,400K,根据自己所用芯片手册查看支持的速度。
- I2C_Init(I2Cx, &I2C_InitStructure);
- I2C_Cmd(I2Cx, ENABLE);
- }
- void I2C_WriteByte(uint8_t addr,uint8_t data)
- {
-
- while( I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
-
- //发送起始信号
- I2C_GenerateSTART(I2Cx, ENABLE);
- //检测EV5事件
- while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT)==ERROR);
- //发送设备写地址
- I2C_Send7bitAddress(I2Cx, OLED_ADDRESS, I2C_Direction_Transmitter);
- //检测EV6事件
- while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);
-
- //发送要操作设备内部的地址
- I2C_SendData(I2Cx, addr);
- //检测EV8_2事件
- while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
-
- I2C_SendData(I2Cx, data);//发送数据
- while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- //发送停止信号
- I2C_GenerateSTOP(I2Cx, ENABLE);
- }
-
- /**
- * @brief OLED写命令
- * @param Command 要写入的命令
- * @retval 无
- */
- void OLED_WriteCommand(unsigned char Command)//写命令
- {
- I2C_WriteByte(0x00, Command);
- }
-
- /**
- * @brief OLED写数据
- * @param Data 要写入的数据
- * @retval 无
- */
- void OLED_WriteData(unsigned char Data)//写数据
- {
- I2C_WriteByte(0x40, Data);
- }
- /**
- * @brief OLED设置光标位置
- * @param Y 以左上角为原点,向下方向的坐标,范围:0~7
- * @param X 以左上角为原点,向右方向的坐标,范围:0~127
- * @retval 无
- */
- void OLED_SetCursor(uint8_t Y, uint8_t X)
- {
- OLED_WriteCommand(0xB0 | Y); //设置Y位置
- OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置低4位
- OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置高4位
- }
- /**
- * @brief OLED清屏
- * @param 无
- * @retval 无
- */
- void OLED_Clear(void)
- {
- uint8_t i, j;
- for (j = 0; j < 8; j++)
- {
- OLED_SetCursor(j, 0);
- for(i = 0; i < 128; i++)
- {
- OLED_WriteData(0x00);
- }
- }
- }
- /**
- * @brief OLED部分清屏
- * @param Line 行位置,范围:1~4
- * @param start 列开始位置,范围:1~16
- * @param end 列开始位置,范围:1~16
- * @retval 无
- */
- void OLED_Clear_Part(uint8_t Line, uint8_t start, uint8_t end)
- {
- uint8_t i,Column;
- for(Column = start; Column <= end; Column++)
- {
- OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
- for (i = 0; i < 8; i++)
- {
- OLED_WriteData(0x00); //显示上半部分内容
- }
- OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
- for (i = 0; i < 8; i++)
- {
- OLED_WriteData(0x00); //显示下半部分内容
- }
- }
- }
- /**
- * @brief OLED显示一个字符
- * @param Line 行位置,范围:1~4
- * @param Column 列位置,范围:1~16
- * @param Char 要显示的一个字符,范围:ASCII可见字符
- * @retval 无
- */
- void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
- {
- uint8_t i;
- OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
- for (i = 0; i < 8; i++)
- {
- OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
- }
- OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
- for (i = 0; i < 8; i++)
- {
- OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
- }
- }
- /**
- * @brief OLED显示字符串
- * @param Line 起始行位置,范围:1~4
- * @param Column 起始列位置,范围:1~16
- * @param String 要显示的字符串,范围:ASCII可见字符
- * @retval 无
- */
- void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
- {
- uint8_t i;
- for (i = 0; String[i] != '\0'; i++)
- {
- OLED_ShowChar(Line, Column + i, String[i]);
- }
- }
- /**
- * @brief OLED次方函数
- * @retval 返回值等于X的Y次方
- */
- uint32_t OLED_Pow(uint32_t X, uint32_t Y)
- {
- uint32_t Result = 1;
- while (Y--)
- {
- Result *= X;
- }
- return Result;
- }
- /**
- * @brief OLED显示数字(十进制,正数)
- * @param Line 起始行位置,范围:1~4
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:0~4294967295
- * @param Length 要显示数字的长度,范围:1~10
- * @retval 无
- */
- void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
- {
- uint8_t i;
- for (i = 0; i < Length; i++)
- {
- OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
- }
- }
- /**
- * @brief OLED显示数字(十进制,带符号数)
- * @param Line 起始行位置,范围:1~4
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:-2147483648~2147483647
- * @param Length 要显示数字的长度,范围:1~10
- * @retval 无
- */
- void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
- {
- uint8_t i;
- uint32_t Number1;
- if (Number >= 0)
- {
- OLED_ShowChar(Line, Column, '+');
- Number1 = Number;
- }
- else
- {
- OLED_ShowChar(Line, Column, '-');
- Number1 = -Number;
- }
- for (i = 0; i < Length; i++)
- {
- OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
- }
- }
- /**
- * @brief OLED显示数字(十六进制,正数)
- * @param Line 起始行位置,范围:1~4
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:0~0xFFFFFFFF
- * @param Length 要显示数字的长度,范围:1~8
- * @retval 无
- */
- void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
- {
- uint8_t i, SingleNumber;
- for (i = 0; i < Length; i++)
- {
- SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
- if (SingleNumber < 10)
- {
- OLED_ShowChar(Line, Column + i, SingleNumber + '0');
- }
- else
- {
- OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
- }
- }
- }
- /**
- * @brief OLED显示数字(二进制,正数)
- * @param Line 起始行位置,范围:1~4
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:0~1111 1111 1111 1111
- * @param Length 要显示数字的长度,范围:1~16
- * @retval 无
- */
- void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
- {
- uint8_t i;
- for (i = 0; i < Length; i++)
- {
- OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
- }
- }
- /**
- * @brief OLED初始化
- * @param 无
- * @retval 无
- */
- void OLED_Init(void)
- {
- uint32_t i, j;
-
- for (i = 0; i < 1000; i++) //上电延时
- {
- for (j = 0; j < 1000; j++);
- }
-
- OLED_I2C_Init(); //端口初始化
-
- OLED_WriteCommand(0xAE); //关闭显示
-
- OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
- OLED_WriteCommand(0x80);
-
- OLED_WriteCommand(0xA8); //设置多路复用率
- OLED_WriteCommand(0x3F);
-
- OLED_WriteCommand(0xD3); //设置显示偏移
- OLED_WriteCommand(0x00);
-
- OLED_WriteCommand(0x40); //设置显示开始行
-
- OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置
-
- OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置
- OLED_WriteCommand(0xDA); //设置COM引脚硬件配置
- OLED_WriteCommand(0x12);
-
- OLED_WriteCommand(0x81); //设置对比度控制
- OLED_WriteCommand(0xCF);
- OLED_WriteCommand(0xD9); //设置预充电周期
- OLED_WriteCommand(0xF1);
- OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别
- OLED_WriteCommand(0x30);
- OLED_WriteCommand(0xA4); //设置整个显示打开/关闭
- OLED_WriteCommand(0xA6); //设置正常/倒转显示
- OLED_WriteCommand(0x8D); //设置充电泵
- OLED_WriteCommand(0x14);
- OLED_WriteCommand(0xAF); //开启显示
-
- OLED_Clear(); //OLED清屏
- }
复制代码
转载自:zeruns
|