功能介绍:
1、由STM32F103和OLED显示器构成一个完整的日期、时间、温度显示系统。日期时间使用STM32F103内部日历系统数据。
2、具有4个控制按键,分别为“SET”,“+”,“-”,“→”四个键,功能描述如下:“SET” 按下时钟进入修改时间设置模式,指示要修改的日期和时间显示字段,对应的该字年、月、日、时、分、秒会有LED灯亮。
3、在设置模式下按动“→”键,可依次循环改变年月日时分秒,标识当前可修改的日期时间字段,此时按“+”、“-”键分别增加、或减少对应的数字,每个字段数字变化有效范围依据所修改的字段有效范围改变。按第七下退出设置模式。
需要的硬件:
1、STM32F103C8T6核心板
2、4针OLED显示屏
3、面包板、跳线、7个LED灯、4个按键、杜邦线
4、STLINKV2
所需的软件:
1、STM32CUBEMX
2、STM32CUBEIDE
3、STM32CubeProgrammer
软件相关配置:
1、使用的硬件资源如下:
2、选择SWD调试模式,不选单片机只能下载一次程序,下一次就下载不了了
3、使能时钟,并配置时钟为72MHZ
4、使能RTC实时时钟,并按如下设置
5、使能定时器TIM3,并按如下设置
6、使能IIC,这个是给OLED屏使用的
7、使能ADC1内部温度测量通道,并按如下设置
8、所有GPIO口的设置如下
9、勾选如下设置
10、生成工程
实物照片:
演示视频
video_20231106_221210
用户代码:
1、oled.c
#include "oled.h"
/**********************************************************
* 初始化命令,根据芯片手册书写
***********************************************************/
uint8_t CMD_Data[]={
0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,
0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,
0xD8, 0x30, 0x8D, 0x14, 0xAF};
void WriteCmd(void)
{
uint8_t i = 0;
for(i=0; i<27; i++)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&CMD_Data[i],1,0x100);
}
}
/**
* @function: void OLED_Init(void)
* @description: OLED初始化
* @return {*}
*/
void OLED_Init(void)
{
HAL_Delay(200);
WriteCmd();
}
/**
* @function: void OLED_WR_CMD(uint8_t cmd)
* @description: 向设备写控制命令
* @param {uint8_t} cmd 芯片手册规定的命令
* @return {*}
*/
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
/**
* @function: void OLED_WR_DATA(uint8_t data)
* @description: 向设备写控制数据
* @param {uint8_t} data 数据
* @return {*}
*/
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}
/**
* @function: void OLED_On(void)
* @description: 更新显示
* @return {*}
*/
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(1);
}
}
/**
* @function: OLED_Clear(void)
* @description: 清屏,整个屏幕是黑色的!和没点亮一样!!!
* @return {*}
*/
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(0);
}
}
/**
* @function: void OLED_Display_On(void)
* @description: 开启OLED显示
* @return {*}
*/
void OLED_Display_On(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X14); //DCDC ON
OLED_WR_CMD(0XAF); //DISPLAY ON,打开显示
}
/**
* @function: void OLED_Display_Off(void)
* @description: 关闭OLED显示
* @return {*}
*/
void OLED_Display_Off(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X10); //DCDC OFF
OLED_WR_CMD(0XAE); //DISPLAY OFF,关闭显示
}
/**
* @function: void OLED_Set_Pos(uint8_t x, uint8_t y)
* @description: 坐标设置
* @param {uint8_t} x,y
* @return {*}
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y); //设置页地址(0~7)
OLED_WR_CMD(((x&0xf0)>>4)|0x10); //设置显示位置—列低地址
OLED_WR_CMD(x&0x0f); //设置显示位置—列高地址
}
/**
* @function: unsigned int oled_pow(uint8_t m,uint8_t n)
* @description: m^n函数
* @param {uint8_t} m,n
* @return {unsigned int} result
*/
unsigned int oled_pow(uint8_t m,uint8_t n)
{
unsigned int result=1;
while(n--)result*=m;
return result;
}
/**
* @function: void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size,uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示一个字符
* @param {uint8_t} x字符开始显示的横坐标
* @param {uint8_t} y字符开始显示的纵坐标
* @param {uint8_t} chr待显示的字符
* @param {uint8_t} Char_Size待显示字符的字体大小,选择字体 16/12
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size,uint8_t Color_Turn)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>128-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i]);
else
OLED_WR_DATA(F8X16[c*16+i]);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i+8]);
else
OLED_WR_DATA(F8X16[c*16+i+8]);
}
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F6x8[c][i]);
else
OLED_WR_DATA(F6x8[c][i]);
}
}
}
/**
* @function: void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_tChar_Size, uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示字符串
* @param {uint8_t} x待显示字符串的开始横坐标x:0~127
* @param {uint8_t} y待显示字符串的开始纵坐标 y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {uint8_t} *chr待显示的字符串
* @param {uint8_t} Char_Size待显示字符串的字体大小,选择字体 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowString(uint8_t x,uint8_t y,char*chr,uint8_t Char_Size, uint8_t Color_Turn)
{
uint8_t j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j],Char_Size, Color_Turn);
if (Char_Size == 12) //6X8的字体列加6,显示下一个字符
x += 6;
else //8X16的字体列加8,显示下一个字符
x += 8;
if (x > 122 && Char_Size==12) //TextSize6x8如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
if (x > 120 && Char_Size== 16) //TextSize8x16如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
j++;
}
}
/**
* @function: void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, Color_Turn)
* @description: 显示数字
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {unsigned int} num:输入的数据
* @param {uint8_t } len:输入的数据位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
}
/**
* @function: void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
* @description: 显示正负浮点数
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {float} num:输入的浮点型数据
* @param {uint8_t } z_ len:整数部分的位数
* @param {uint8_t } f_len: 小数部分的位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp,i=0;//i为负数标志位
uint8_t enshow;
int z_temp,f_temp;
if(num<0)
{
z_len+=1;
i=1;
num=-num;
}
z_temp=(int)num;
//整数部分
for(t=0;t<z_len;t++)
{
temp=(z_temp/oled_pow(10,z_len-t-1))%10;
if(enshow==0 && t<(z_len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}
else
enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
//小数点
OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2, Color_Turn);
f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));
//小数部分
for(t=0;t<f_len;t++)
{
temp=(f_temp/oled_pow(10,f_len-t-1))%10;
OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2, Color_Turn);
}
if(i==1)//如果为负,就将最前的一位赋值‘-’
{
OLED_ShowChar(x,y,'-',size2, Color_Turn);
i=0;
}
}
/**
* @function: void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
* @description: 在OLED特定位置开始显示16X16汉字
* @param {uint8_t} x待显示的汉字起始横坐标x: 0~112,两列汉字之间需要间隔16
* @param {uint8_t} y待显示的汉字起始纵坐标 y: 0~6 , 两行汉字之间需要间隔2
* @param {uint8_t} no待显示的汉字编号
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
{
uint8_t t=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no][t]); //显示汉字的上半部分
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no+1][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no+1][t]);//显示汉字的上半部分
}
}
/**
* @function: void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
* @description: 在OLED特定区域显示BMP图片
* @param {uint8_t} x0图像开始显示横坐标 x0:0~127
* @param {uint8_t} y0图像开始显示纵坐标 y0:0~7
* @param {uint8_t} x1图像结束显示横坐标 x1:1~128
* @param {uint8_t} y1图像结束显示纵坐标 y1:1~8
* @param {uint8_t} *BMP待显示的图像数据
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
{
uint32_t j = 0;
uint8_t x = 0, y = 0;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
if (Color_Turn)
OLED_WR_DATA(~BMP[j++]);//显示反相图片
else
OLED_WR_DATA(BMP[j++]);//显示图片
}
}
}
/**
* @function: void OLED_HorizontalShift(uint8_t direction)
* @description: 屏幕内容水平全屏滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @return {*}
*/
void OLED_HorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频
// 0x00-5帧, 0x01-64帧, 0x02-128帧, 0x03-256帧, 0x04-3帧, 0x05-4帧, 0x06-25帧, 0x07-2帧,
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
* @description: 屏幕部分内容水平滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @param {uint8_t} start 开始页地址 0x00~0x07
* @param {uint8_t} end 结束页地址 0x01~0x07
* @return {*}
*/
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(start);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,0x07即滚动速度2帧
OLED_WR_CMD(end);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_VerticalAndHorizontalShift(uint8_t direction)
* @description: 屏幕内容垂直水平全屏滚动播放
* @param {uint8_t} direction 右上滚动 0x29
* 左上滚动 0x2A
* @return {*}
*/
void OLED_VerticalAndHorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x01);//虚拟字节设置
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,即滚动速度
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x01);//垂直滚动偏移量
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_DisplayMode(uint8_t mode)
* @description: 屏幕内容取反显示
* @param {uint8_t} direction ON 0xA7 ,
* OFF 0xA6 默认此模式,设置像素点亮
* @return {*}
*/
void OLED_DisplayMode(uint8_t mode)
{
OLED_WR_CMD(mode);
}
/**
* @function: void OLED_IntensityControl(uint8_t intensity)
* @description: 屏幕亮度调节
* @param {uint8_t} intensity 0x00~0xFF,RESET=0x7F
* @return {*}
*/
void OLED_IntensityControl(uint8_t intensity)
{
OLED_WR_CMD(0x81);
OLED_WR_CMD(intensity);
}
2、oled.h
//oled.h
#ifndef OLED_OLED_H_
#define OLED_OLED_H_
#include "stm32f1xx_hal.h"
#include "oledfont.h"
extern I2C_HandleTypeDef hi2c1;
void WriteCmd(void);
void OLED_WR_CMD(uint8_t cmd);
void OLED_WR_DATA(uint8_t data);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Set_Pos(uint8_t x, uint8_t y);
void OLED_On(void);
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2,uint8_t Color_Turn);
void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn);
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size,uint8_t Color_Turn);
void OLED_ShowString(uint8_t x,uint8_t y,char*chr,uint8_t Char_Size,uint8_t Color_Turn);
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no,uint8_t Color_Turn);
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn);
void OLED_HorizontalShift(uint8_t direction);
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end);
void OLED_VerticalAndHorizontalShift(uint8_t direction);
void OLED_DisplayMode(uint8_t mode);
void OLED_IntensityControl(uint8_t intensity);
#endif /* OLED_OLED_H_ */
3、更改日期、时间函数key_set()
void key_set(void){
unsigned char ic =0;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0);
OLED_Clear();
OLED_ShowString(0, 6, "SETTING", 16, 0);
while((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)||(ic<6)){
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11)==0);
ic++;
if(ic>6)
ic=0;
}
if(ic==0){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0){
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0);
SetDate.Year++;
if(SetDate.Year>99)
SetDate.Year=0;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0);
SetDate.Year--;
}
HAL_RTC_SetDate(&hrtc,&SetDate,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &SetDate, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
OLED_ShowString(0, 4, "Year ", 16, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_SET);
}
if(ic==1){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0){
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0);
SetDate.Month++;
if(SetDate.Month>12)
SetDate.Month=1;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0);
if(SetDate.Month>1)
SetDate.Month--;
}
HAL_RTC_SetDate(&hrtc,&SetDate,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &SetDate, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
OLED_ShowString(0, 4, "Month ", 16, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,GPIO_PIN_SET);
}
if(ic==2){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0){
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0);
SetDate.Date++;
if(SetDate.Date>31)
SetDate.Date = 1;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0);
if(SetDate.Date>1)
SetDate.Date--;
}
HAL_RTC_SetDate(&hrtc,&SetDate,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &SetDate, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
OLED_ShowString(0, 4, "Date ", 16, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2,GPIO_PIN_SET);
}
if(ic==3){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0){
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0);
SetTime.Hours++;
if(SetTime.Hours>23)
SetTime.Hours=0;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0);
if(SetTime.Hours>0)
SetTime.Hours--;
}
HAL_RTC_SetTime(&hrtc,&SetTime,RTC_FORMAT_BIN);
HAL_RTC_GetTime(&hrtc, &SetTime, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
OLED_ShowString(0, 4, "Hours ", 16, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3,GPIO_PIN_SET);
}
if(ic==4){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0){
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0);
SetTime.Minutes++;
if(SetTime.Minutes>59)
SetTime.Minutes=0;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0);
if(SetTime.Minutes>0)
SetTime.Minutes--;
}
HAL_RTC_SetTime(&hrtc,&SetTime,RTC_FORMAT_BIN);
HAL_RTC_GetTime(&hrtc, &SetTime, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
OLED_ShowString(0, 4, "Minutes ", 16, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET);
}
if(ic==5){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0){
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==0);
SetTime.Seconds++;
if(SetTime.Seconds>59)
SetTime.Seconds=0;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0);
if(SetTime.Seconds>0)
SetTime.Seconds--;
}
HAL_RTC_SetTime(&hrtc,&SetTime,RTC_FORMAT_BIN);
HAL_RTC_GetTime(&hrtc, &SetTime, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
OLED_ShowString(0, 4, "Seconds ", 16, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,GPIO_PIN_SET);
}
if(ic==6){
OLED_Clear();
sprintf(tbuf,"20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
ic=0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,GPIO_PIN_RESET);
break;
}
}
}
}
4、获取日期、时间函数GetCalender()
void GetCalender(void){
HAL_RTC_GetTime(&hrtc, &SetTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &SetDate, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",SetDate.Year,
SetDate.Month,SetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",SetTime.Hours,
SetTime.Minutes,SetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
}
5、获取温度函数GetTemperature()
void GetTemperature(void)
{
float Temperature,AD_Value,Vol_Value;
HAL_ADC_Start(&hadc1); //启动ADC转换
HAL_ADC_PollForConversion(&hadc1,10); //等待转换完成,10ms表示超时时间
AD_Value = HAL_ADC_GetValue(&hadc1); //读取ADC转换数据(12位数据)
Vol_Value = AD_Value*(3.3/4096); //AD值乘以分辨率即为电压值
Temperature = (1.43 - Vol_Value)/0.0043 + 25; //根据公式算出温度值
OLED_ShowString(0, 4, "Temp:", 16, 0);
OLED_Showdecimal(44,4,Temperature,2,2,16,0);
OLED_ShowString(88, 4, "C", 16, 0);
}
6、main.c的关键代码
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include "stdio.h"
RTC_TimeTypeDef GetTime ;
RTC_DateTypeDef GetDate ;
RTC_TimeTypeDef SetTime ;
RTC_DateTypeDef SetDate ;
RTC_TimeTypeDef SetAlarm;
char tbuf[40];
char tbu[40];
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_RTC_Init();
MX_I2C1_Init();
MX_TIM3_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_TIM_Base_Start_IT(&htim3);
OLED_Init();
OLED_Clear();
// OLED_ShowString(0, 0, "tlm", 16, 1);
HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &GetDate, RTC_FORMAT_BIN);
sprintf(tbuf,"Date:20%02d-%02d-%02d",GetDate.Year,
GetDate.Month,GetDate.Date); //将日期的数据打包到tbuf数组中
OLED_ShowString(0, 0, tbuf, 16, 0);
sprintf(tbuf,"Time:%02d:%02d:%02d",GetTime.Hours,
GetTime.Minutes,GetTime.Seconds); //将时间的数据打包到tbuf数组中
OLED_ShowString(0, 2, tbuf, 16, 0);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
key_set();
GetCalender();
GetTemperature();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
结束:
附完整的工程文件:链接:https://pan.baidu.com/s/1fy7jTGq4uOygJyMbkUzYNw
提取码:9k4t