你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32单片机读取AHT10温湿度传感器数据

[复制链接]
攻城狮Melo 发布时间:2022-11-13 14:48
实现效果图
微信图片_20221113144849.jpg

微信图片_20221113144846.gif

I2C协议简介
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备(那些电平转化芯片),现在被广泛地使用在系统内多个集成电路(IC)间的通讯。
I2C只有一根数据总线 SDA(Serial Data Line),串行数据总线,只能一位一位的发送数据,属于串行通信,采用半双工通信
半双工通信:可以实现双向的通信,但不能在两个方向上同时进行,必须轮流交替进行,其实也可以理解成一种可以切换方向的单工通信,同一时刻必须只能一个方向传输,只需一根数据线.
对于I2C通讯协议把它分为物理层和协议层物理层规定通讯系统中具有机械、电子功能部分的特性(硬件部分),确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准(软件层面)。

I2C物理层
I2C 通讯设备之间的常用连接方式
微信图片_20221113144841.png

(1) 它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。
(2) 一个 I2C 总线只使用两条总线线路,一条双向串行数据线SDA(Serial Data Line ),一条串行时钟线SCL(Serial Data Line )。数据线即用来表示数据,时钟线用于数据收发同步
(3) 总线通过上拉电阻接到电源。当 I2C 设备空闲时会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平
I2C通信时单片机GPIO口必须设置为开漏输出,否则可能会造成短路。

AHT10温湿度传感器介绍
AHT10是一款国产的温湿度传感器芯片,价格便宜,精度还高,体积也小。
AHT10配有一个全新设计的ASIC专用芯片、一个经过改进的MEMS半导体电容式湿度传感元件和一个标准的片上温度传感元件,其性能已经大大提升甚至超出了前一代传感器的可靠性水平,新一代温湿度传感器,经过改进使其在恶劣环境下的性能更稳定。

微信图片_20221113144836.png

微信图片_20221113144833.png
微信图片_20221113144829.png

浏览数据手册可以得到一个大概信息:
  • 温度范围:-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就行,最低位标准库会处理的。

微信图片_20221113144825.png

读取温湿度数据
微信图片_20221113144802.png

微信图片_20221113144757.png

从数据手册可知,一个测量周期包概括三个步骤:
  • 发送测量命令
  • 等待测量完成
  • 读取测量后的数据 

总结如下:
  • 发送测量命令:先发送写入指令(0x70),再发送触发测量指令(0xAC),再发送命令参数(0x33和0x00)。
  • 等待测量完成:数据手册上写的75ms,等待的时间大于这个就行了。
  • 接收数据:发送读取指令(0x71),连续接收6个字节数据。接收到的第一个字节是状态字,检查状态字第3位校准使能位是否为1,不为1就发送初始化命令,检查第7位忙闲指示,如果是0为测量完成,进行下一步。
  • 对接收到的数据进行转换处理。


数据的计算
由AHT10数据手册可知

微信图片_20221113144753.png

例如:采集到的湿度数值是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
  1. #include "stm32f10x.h"                  // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "IWDG.h"
  5. #include "AHT10.h"


  6. uint16_t numlen(uint16_t num);

  7. int main(void)
  8. {
  9.   IWDG_Configuration();  //初始化看门狗
  10.   OLED_Init();      //初始化OLED屏
  11.   AHT10_Init();      //初始化AHT10
  12.   
  13.   OLED_ShowString(1, 1, "T:");
  14.   OLED_ShowString(2, 1, "H:");

  15.   uint32_t a=0;
  16.   uint16_t err_count=0;
  17.   
  18.   while (1)
  19.   {
  20.     a++;
  21.     OLED_ShowNum(3, 1, a, 9);//计数显示,方便观察程序是否正常运行
  22.     if(a==999999999)a=0;

  23.     float Temp,Hum;      //声明变量存放温湿度数据
  24.    
  25.   /*
  26.   https://blog.zeruns.tech
  27.   */

  28.     if(ReadAHT10(&Hum,&Temp))  //读取温湿度数据
  29.     {
  30.       if(Temp>=0)
  31.       {
  32.         char String[10];
  33.         sprintf(String, "+%.2fC", Temp);//格式化字符串输出到字符串变量
  34.         OLED_ShowString(1, 3, String);  //显示温度

  35.         sprintf(String, " %.2f%%", Hum);//格式化字符串输出到字符串变量
  36.         OLED_ShowString(2, 3, String);  //显示湿度
  37.       }else
  38.       {
  39.         char String[10];
  40.         sprintf(String, "-%.2fC", Temp);//格式化字符串输出到字符串变量
  41.         OLED_ShowString(1, 3, String);  //显示温度
  42.         
  43.         sprintf(String, " %.2f%%", Hum);//格式化字符串输出到字符串变量
  44.         OLED_ShowString(2, 3, String);  //显示湿度
  45.       }
  46.     }
  47.     else
  48.     {
  49.       err_count++;
  50.       OLED_ShowNum(4,1, err_count, 5);  //显示错误次数计数
  51.     }

  52.     Delay_ms(100);  //延时100毫秒

  53.     IWDG_FeedDog();  //喂狗(看门狗,超过1秒没有执行喂狗则自动复位)
  54.   }
  55. }
复制代码

AHT10.c
  1. #include "stm32f10x.h"
  2. #include "Delay.h"
  3. #include "OLED.h"

  4. /*AHT10地址*/
  5. #define AHT10_ADDRESS 0x38<<1 //从机地址是7位,最后一位是传输方向位,所以左移一位

  6. /*设置使用哪一个I2C*/
  7. #define I2Cx I2C1

  8. /*
  9. https://blog.zeruns.tech
  10. */


  11. /*发送起始信号*/
  12. void AHT10_I2C_START(){
  13.     while( I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));//等待总线空闲
  14.   I2C_GenerateSTART(I2Cx, ENABLE);//发送起始信号
  15.   while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT)==ERROR);//检测EV5事件
  16. }

  17. /*发送停止信号*/
  18. void AHT10_I2C_STOP(){
  19.     I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
  20. }

  21. /**
  22.   * @brief  发送3个字节数据
  23.   * @param  cmd 命令字节
  24.   * @param  DATA0 第0个参数
  25.   * @param  DATA1 第1个参数
  26.   * @retval 无
  27.   */
  28. void AHT10_WriteByte(uint8_t cmd, uint8_t DATA0, uint8_t DATA1)
  29. {
  30.   AHT10_I2C_START();  //发送起始信号
  31.   
  32.   I2C_Send7bitAddress(I2Cx, AHT10_ADDRESS, I2C_Direction_Transmitter);    //发送设备写地址
  33.   while(I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);  //检测EV6事件

  34.     I2C_SendData(I2Cx, cmd);//发送命令
  35.   while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件

  36.     I2C_SendData(I2Cx, DATA0);//发送命令参数高8位数据
  37.   while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
  38.    
  39.   I2C_SendData(I2Cx, DATA1);//发送命令参数低8位数据
  40.   while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
  41.   
  42.   I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号  
  43. }


  44. /**
  45.   * @brief  发送命令读取AHT10的状态
  46.   * @retval 读取到的状态字节
  47.   */
  48. /*uint8_t AHT10_ReadStatus(void){
  49.     AHT10_I2C_START();//发送起始信号  
  50.   I2C_Send7bitAddress(I2Cx,AHT10_ADDRESS,I2C_Direction_Receiver);//发送设备读地址
  51.   while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR);//检测EV6事件
  52.     while (!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_RECEIVED));//检测EV7事件
  53.   I2C_AcknowledgeConfig(I2Cx, DISABLE); //关闭应答信号
  54.   uint8_t status = I2C_ReceiveData(I2Cx);//读取数据并返回
  55.   AHT10_I2C_STOP();   //发送停止信号
  56.   I2C_AcknowledgeConfig(I2Cx,ENABLE);//重新开启应答信号
  57.   return status;
  58. }*/

  59. /**
  60.   * @brief  读取数据
  61.   * @retval 读取到的字节数据
  62.   */
  63. uint8_t AHT10_ReadData(void)
  64. {
  65.     while (!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_RECEIVED));//检测EV7事件
  66.   return I2C_ReceiveData(I2Cx);//读取数据并返回
  67. }

  68. /*软件复位AHT10*/
  69. void AHT10_SoftReset(void)                    
  70. {
  71.     AHT10_I2C_START();  //发送起始信号
  72.   I2C_Send7bitAddress(I2Cx, AHT10_ADDRESS, I2C_Direction_Transmitter);    //发送设备写地址
  73.   while(I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);  //检测EV6事件
  74.     I2C_SendData(I2Cx, 0xBA);//发送软复位命令
  75.   while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检测EV8事件
  76.     I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
  77.   Delay_ms(20);
  78. }


  79. /*引脚初始化*/
  80. void AHT10_Init(void)
  81. {
  82.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);  //使能I2C1时钟
  83.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟

  84.   /*STM32F103芯片的硬件I2C1: PB6 -- SCL; PB7 -- SDA */
  85.   GPIO_InitTypeDef  GPIO_InitStructure;               //定义结构体配置GPIO
  86.   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  87.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
  88.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;    //设置输出模式为开漏输出,需接上拉电阻
  89.   GPIO_Init(GPIOB, &GPIO_InitStructure);              //初始化GPIO
  90.   
  91.   I2C_DeInit(I2Cx);  //将外设I2C寄存器重设为缺省值
  92.   I2C_InitTypeDef  I2C_InitStructure;                 //定义结构体配置I2C
  93.   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;      //工作模式
  94.   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  //时钟占空比,Tlow/Thigh = 2
  95.   I2C_InitStructure.I2C_OwnAddress1 = 0x88;  //主机的I2C地址,用不到则随便写,无影响
  96.   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;  //使能应答位
  97.   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//设置地址长度7位
  98.   I2C_InitStructure.I2C_ClockSpeed = 400000;  //I2C传输速度,400K,根据自己所用芯片手册查看支持的速度。  
  99.   I2C_Init(I2Cx, &I2C_InitStructure);         //初始化I2C

  100.   I2C_Cmd(I2Cx, ENABLE);  //启用I2C
  101.   Delay_ms(20);//上电延时
  102.   AHT10_WriteByte(0XE1,0X08,0x00);//发送指令初始化
  103.   Delay_ms(20);

  104. }

  105. /**
  106.   * @brief  读取AHT10数据
  107.   * @param  *Hum 湿度
  108.   * @param  *Temp 温度
  109.   * @retval 1 - 读取成功;0 - 读取失败
  110.   */
  111. uint8_t ReadAHT10(float *Hum,float *Temp)
  112. {
  113.   uint8_t Data[5];//声明变量存放读取的数据

  114.   AHT10_WriteByte(0XAC,0X33,0x00);//发送指令触发测量

  115.   Delay_ms(70);  //延时70毫秒等待测量完成

  116.   AHT10_I2C_START();//发送起始信号  
  117.   I2C_Send7bitAddress(I2Cx,AHT10_ADDRESS,I2C_Direction_Receiver);//发送设备读地址
  118.   while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR);//检测EV6事件
  119.   
  120.   uint8_t i;
  121.   for(i=0;i<6;i++)//循环6次读取6个字节数据
  122.   {
  123.     if (i == 5)  //读取最后1个字节时关闭应答信号
  124.     {
  125.       I2C_AcknowledgeConfig(I2Cx, DISABLE); //关闭应答信号
  126.     }
  127.     Data[i] = AHT10_ReadData();  //读取数据
  128.     if (i == 5)
  129.       I2C_GenerateSTOP(I2Cx, ENABLE); //发送停止信号
  130.   }
  131.   I2C_AcknowledgeConfig(I2Cx,ENABLE);//重新开启应答信号

  132.   if( (Data[0]&0x08) == 0 )//0x08(00001000)检查状态字节第3位(校准使能位)是否为0
  133.   {
  134.     AHT10_WriteByte(0XE1,0X08,0x00);  //发送指令初始化
  135.     Delay_ms(20);
  136.     return 0;
  137.   }
  138.   else if( (Data[0]&0x80) == 0 )//0x80(10000000)检查状态字节第7位(忙闲指示)是否为0
  139.   {
  140.    
  141.     uint32_t SRH = (Data[1]<<12) | (Data[2]<<4) | (Data[3]>>4);  //湿度数据处理
  142.     uint32_t ST = ((Data[3]&0x0f)<<16) | (Data[4]<<8) | Data[5];//温度数据处理

  143.     *Hum = (SRH * 100.0) / 1024.0 / 1024;     //根据手册给的公式转换湿度数据
  144.     *Temp = (ST * 200.0) / 1024.0 / 1024 - 50; //根据手册给的公式转换温度数据

  145.     return 1;
  146.   }

  147.   I2C_GenerateSTOP(I2Cx, ENABLE);//发送停止信号
  148.   return 0;  

  149. }

  150. /*
  151. https://blog.zeruns.tech
  152. */
复制代码

OLED.c
  1. #include "stm32f10x.h"
  2. #include "OLED_Font.h"

  3. /*OLED屏地址*/
  4. #define OLED_ADDRESS 0x78

  5. /*设置哪一个使用I2C*/
  6. #define I2Cx I2C1

  7. /*
  8. https://blog.zeruns.tech
  9. */

  10. /*引脚初始化*/
  11. void OLED_I2C_Init(void)
  12. {
  13.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);  //使能I2C1时钟
  14.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟

  15.   /*STM32F103芯片的硬件I2C: PB6 -- SCL; PB7 -- SDA */
  16.   GPIO_InitTypeDef  GPIO_InitStructure;
  17.   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  18.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  19.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;    //设置输出模式为开漏输出,需接上拉电阻
  20.   GPIO_Init(GPIOB, &GPIO_InitStructure);
  21.   
  22.   I2C_DeInit(I2Cx);  //将外设I2C寄存器重设为缺省值
  23.   I2C_InitTypeDef  I2C_InitStructure;
  24.   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;      //工作模式
  25.   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  //时钟占空比,Tlow/Thigh = 2
  26.   I2C_InitStructure.I2C_OwnAddress1 = 0x88;  //主机的I2C地址,用不到则随便写,无影响
  27.   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;  //使能应答位
  28.   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//设置地址长度7位
  29.   I2C_InitStructure.I2C_ClockSpeed = 400000;  //I2C传输速度,400K,根据自己所用芯片手册查看支持的速度。  
  30.   I2C_Init(I2Cx, &I2C_InitStructure);

  31.   I2C_Cmd(I2Cx, ENABLE);
  32. }

  33. void I2C_WriteByte(uint8_t addr,uint8_t data)
  34. {
  35.   
  36.   while( I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
  37.   
  38.   //发送起始信号
  39.   I2C_GenerateSTART(I2Cx, ENABLE);
  40.   //检测EV5事件
  41.   while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT)==ERROR);
  42.   //发送设备写地址
  43.   I2C_Send7bitAddress(I2Cx, OLED_ADDRESS, I2C_Direction_Transmitter);
  44.   //检测EV6事件
  45.   while( I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);
  46.   
  47.   //发送要操作设备内部的地址
  48.   I2C_SendData(I2Cx, addr);
  49.   //检测EV8_2事件
  50.   while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  51.   
  52.   I2C_SendData(I2Cx, data);//发送数据
  53.   while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  54.   //发送停止信号
  55.   I2C_GenerateSTOP(I2Cx, ENABLE);
  56. }

  57. /**
  58.   * @brief  OLED写命令
  59.   * @param  Command 要写入的命令
  60.   * @retval 无
  61.   */
  62. void OLED_WriteCommand(unsigned char Command)//写命令
  63. {
  64.   I2C_WriteByte(0x00, Command);
  65. }

  66. /**
  67.   * @brief  OLED写数据
  68.   * @param  Data 要写入的数据
  69.   * @retval 无
  70. */
  71. void OLED_WriteData(unsigned char Data)//写数据
  72. {
  73.   I2C_WriteByte(0x40, Data);
  74. }

  75. /**
  76.   * @brief  OLED设置光标位置
  77.   * @param  Y 以左上角为原点,向下方向的坐标,范围:0~7
  78.   * @param  X 以左上角为原点,向右方向的坐标,范围:0~127
  79.   * @retval 无
  80.   */
  81. void OLED_SetCursor(uint8_t Y, uint8_t X)
  82. {
  83.   OLED_WriteCommand(0xB0 | Y);          //设置Y位置
  84.   OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));  //设置X位置低4位
  85.   OLED_WriteCommand(0x00 | (X & 0x0F));      //设置X位置高4位
  86. }

  87. /**
  88.   * @brief  OLED清屏
  89.   * @param  无
  90.   * @retval 无
  91.   */
  92. void OLED_Clear(void)
  93. {  
  94.   uint8_t i, j;
  95.   for (j = 0; j < 8; j++)
  96.   {
  97.     OLED_SetCursor(j, 0);
  98.     for(i = 0; i < 128; i++)
  99.     {
  100.       OLED_WriteData(0x00);
  101.     }
  102.   }
  103. }

  104. /**
  105.   * @brief  OLED部分清屏
  106.   * @param  Line 行位置,范围:1~4
  107.   * @param  start 列开始位置,范围:1~16
  108.   * @param  end 列开始位置,范围:1~16
  109.   * @retval 无
  110.   */
  111. void OLED_Clear_Part(uint8_t Line, uint8_t start, uint8_t end)
  112. {  
  113.   uint8_t i,Column;
  114.   for(Column = start; Column <= end; Column++)
  115.   {
  116.     OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);    //设置光标位置在上半部分
  117.     for (i = 0; i < 8; i++)
  118.     {
  119.       OLED_WriteData(0x00);      //显示上半部分内容
  120.     }
  121.     OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);  //设置光标位置在下半部分
  122.     for (i = 0; i < 8; i++)
  123.     {
  124.       OLED_WriteData(0x00);    //显示下半部分内容
  125.     }
  126.   }
  127. }

  128. /**
  129.   * @brief  OLED显示一个字符
  130.   * @param  Line 行位置,范围:1~4
  131.   * @param  Column 列位置,范围:1~16
  132.   * @param  Char 要显示的一个字符,范围:ASCII可见字符
  133.   * @retval 无
  134.   */
  135. void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
  136. {        
  137.   uint8_t i;
  138.   OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);    //设置光标位置在上半部分
  139.   for (i = 0; i < 8; i++)
  140.   {
  141.     OLED_WriteData(OLED_F8x16[Char - ' '][i]);      //显示上半部分内容
  142.   }
  143.   OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);  //设置光标位置在下半部分
  144.   for (i = 0; i < 8; i++)
  145.   {
  146.     OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);    //显示下半部分内容
  147.   }
  148. }

  149. /**
  150.   * @brief  OLED显示字符串
  151.   * @param  Line 起始行位置,范围:1~4
  152.   * @param  Column 起始列位置,范围:1~16
  153.   * @param  String 要显示的字符串,范围:ASCII可见字符
  154.   * @retval 无
  155.   */
  156. void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
  157. {
  158.   uint8_t i;
  159.   for (i = 0; String[i] != '\0'; i++)
  160.   {
  161.     OLED_ShowChar(Line, Column + i, String[i]);
  162.   }
  163. }

  164. /**
  165.   * @brief  OLED次方函数
  166.   * @retval 返回值等于X的Y次方
  167.   */
  168. uint32_t OLED_Pow(uint32_t X, uint32_t Y)
  169. {
  170.   uint32_t Result = 1;
  171.   while (Y--)
  172.   {
  173.     Result *= X;
  174.   }
  175.   return Result;
  176. }

  177. /**
  178.   * @brief  OLED显示数字(十进制,正数)
  179.   * @param  Line 起始行位置,范围:1~4
  180.   * @param  Column 起始列位置,范围:1~16
  181.   * @param  Number 要显示的数字,范围:0~4294967295
  182.   * @param  Length 要显示数字的长度,范围:1~10
  183.   * @retval 无
  184.   */
  185. void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
  186. {
  187.   uint8_t i;
  188.   for (i = 0; i < Length; i++)              
  189.   {
  190.     OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
  191.   }
  192. }

  193. /**
  194.   * @brief  OLED显示数字(十进制,带符号数)
  195.   * @param  Line 起始行位置,范围:1~4
  196.   * @param  Column 起始列位置,范围:1~16
  197.   * @param  Number 要显示的数字,范围:-2147483648~2147483647
  198.   * @param  Length 要显示数字的长度,范围:1~10
  199.   * @retval 无
  200.   */
  201. void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
  202. {
  203.   uint8_t i;
  204.   uint32_t Number1;
  205.   if (Number >= 0)
  206.   {
  207.     OLED_ShowChar(Line, Column, '+');
  208.     Number1 = Number;
  209.   }
  210.   else
  211.   {
  212.     OLED_ShowChar(Line, Column, '-');
  213.     Number1 = -Number;
  214.   }
  215.   for (i = 0; i < Length; i++)              
  216.   {
  217.     OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
  218.   }
  219. }

  220. /**
  221.   * @brief  OLED显示数字(十六进制,正数)
  222.   * @param  Line 起始行位置,范围:1~4
  223.   * @param  Column 起始列位置,范围:1~16
  224.   * @param  Number 要显示的数字,范围:0~0xFFFFFFFF
  225.   * @param  Length 要显示数字的长度,范围:1~8
  226.   * @retval 无
  227.   */
  228. void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
  229. {
  230.   uint8_t i, SingleNumber;
  231.   for (i = 0; i < Length; i++)              
  232.   {
  233.     SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
  234.     if (SingleNumber < 10)
  235.     {
  236.       OLED_ShowChar(Line, Column + i, SingleNumber + '0');
  237.     }
  238.     else
  239.     {
  240.       OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
  241.     }
  242.   }
  243. }

  244. /**
  245.   * @brief  OLED显示数字(二进制,正数)
  246.   * @param  Line 起始行位置,范围:1~4
  247.   * @param  Column 起始列位置,范围:1~16
  248.   * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  249.   * @param  Length 要显示数字的长度,范围:1~16
  250.   * @retval 无
  251.   */
  252. void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
  253. {
  254.   uint8_t i;
  255.   for (i = 0; i < Length; i++)              
  256.   {
  257.     OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
  258.   }
  259. }

  260. /**
  261.   * @brief  OLED初始化
  262.   * @param  无
  263.   * @retval 无
  264.   */
  265. void OLED_Init(void)
  266. {
  267.   uint32_t i, j;
  268.   
  269.   for (i = 0; i < 1000; i++)      //上电延时
  270.   {
  271.     for (j = 0; j < 1000; j++);
  272.   }
  273.   
  274.   OLED_I2C_Init();      //端口初始化
  275.   
  276.   OLED_WriteCommand(0xAE);  //关闭显示
  277.   
  278.   OLED_WriteCommand(0xD5);  //设置显示时钟分频比/振荡器频率
  279.   OLED_WriteCommand(0x80);
  280.   
  281.   OLED_WriteCommand(0xA8);  //设置多路复用率
  282.   OLED_WriteCommand(0x3F);
  283.   
  284.   OLED_WriteCommand(0xD3);  //设置显示偏移
  285.   OLED_WriteCommand(0x00);
  286.   
  287.   OLED_WriteCommand(0x40);  //设置显示开始行
  288.   
  289.   OLED_WriteCommand(0xA1);  //设置左右方向,0xA1正常 0xA0左右反置
  290.   
  291.   OLED_WriteCommand(0xC8);  //设置上下方向,0xC8正常 0xC0上下反置

  292.   OLED_WriteCommand(0xDA);  //设置COM引脚硬件配置
  293.   OLED_WriteCommand(0x12);
  294.   
  295.   OLED_WriteCommand(0x81);  //设置对比度控制
  296.   OLED_WriteCommand(0xCF);

  297.   OLED_WriteCommand(0xD9);  //设置预充电周期
  298.   OLED_WriteCommand(0xF1);

  299.   OLED_WriteCommand(0xDB);  //设置VCOMH取消选择级别
  300.   OLED_WriteCommand(0x30);

  301.   OLED_WriteCommand(0xA4);  //设置整个显示打开/关闭

  302.   OLED_WriteCommand(0xA6);  //设置正常/倒转显示

  303.   OLED_WriteCommand(0x8D);  //设置充电泵
  304.   OLED_WriteCommand(0x14);

  305.   OLED_WriteCommand(0xAF);  //开启显示
  306.    
  307.   OLED_Clear();        //OLED清屏
  308. }
复制代码

转载自:zeruns



收藏 评论0 发布时间:2022-11-13 14:48

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版