题目要求
平台 STM32F411CE,IO口连接如下图
配置CubeMX工程,暂时不开启定时器,先把每项功能调通以后再通过中断或者操作系统功能结合
第一步开启串口,USART1开发板未引出,因此开启USART2,顺便加一个delay_us,勾选use microlib后,串口2就可以正常输出了
//串口重定向
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart2, &ch, 1, 0xffff);
return ch;
}
void delay_us(volatile uint32_t us)
{
volatile uint16_t i,j;
while(us--)
{
for(i=0;i<11;i++)
j++;
}
}
第二步调试OLED,OLED驱动为SSD1306,IIC模式。
#include "oled.h"
#include "oledfont.h"
//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
/**
* @brief OLED写入命令
* @param cmd - 待写入命令
* @note 移植时,请使用自己的底层API实现
*/
static void OLED_Write_Cmd(uint8_t cmd)
{
uint8_t buf[2];
buf[0] = 0x00; //control byte
buf[1] = cmd;
//使用HAL库的API实现
HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf, 2, 0xFFFF);
}
/**
* @brief OLED写入数据
* @param cmd - 待写入数据
* @note 移植时,请使用自己的底层API实现
*/
static void OLED_Write_Dat(uint8_t dat)
{
uint8_t buf[2];
buf[0] = 0x40; //control byte
buf[1] = dat;
//使用HAL库的API实现
HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf, 2, 0xFFFF);
}
/**
* @brief OLED设置显示位置
* @param x - X方向位置
* @param y - Y方向位置
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_Write_Cmd(0xb0+y);
OLED_Write_Cmd(((x&0xf0)>>4)|0x10);
OLED_Write_Cmd((x&0x0f)|0x01);
}
/**
* @brief OLED开启显示
*/
void OLED_Display_On(void)
{
OLED_Write_Cmd(0X8D); //SET DCDC命令
OLED_Write_Cmd(0X14); //DCDC ON
OLED_Write_Cmd(0XAF); //DISPLAY ON
}
/**
* @brief OLED关闭显示
*/
void OLED_Display_Off(void)
{
OLED_Write_Cmd(0X8D); //SET DCDC命令
OLED_Write_Cmd(0X10); //DCDC OFF
OLED_Write_Cmd(0XAE); //DISPLAY OFF
}
/**
* @brief OLED清屏函数(清屏之后屏幕全为黑色)
*/
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_Write_Cmd(0xb0+i); //设置页地址(0~7)
OLED_Write_Cmd(0x00); //设置显示位置—列低地址
OLED_Write_Cmd(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
{
OLED_Write_Dat(0);
}
}
}
/**
* @brief OLED显示全开(所有像素点全亮)
*/
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_Write_Cmd(0xb0+i); //设置页地址(0~7)
OLED_Write_Cmd(0x00); //设置显示位置—列低地址
OLED_Write_Cmd(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
{
OLED_Write_Dat(1);
}
}
}
/**
* @brief 在指定位置显示一个ASCII字符
* @param x - 0 - 127
* @param y - 0 - 7
* @param chr - 待显示的ASCII字符
* @param size - ASCII字符大小
* 字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size)
{
uint8_t c=0,i=0;
c = chr-' ';
if(x > 128-1)
{
x=0;
y++;
}
if(size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
OLED_Write_Dat(F8X16[c*16+i]);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
OLED_Write_Dat(F8X16[c*16+i+8]);
}
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
OLED_Write_Dat(F6x8[c][i]);
}
}
}
/**
* @brief OLED 专用pow函数
* @param m - 底数
* @param n - 指数
*/
static uint32_t oled_pow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
/**
* @brief 在指定位置显示一个整数
* @param x - 0 - 127
* @param y - 0 - 7
* @param num - 待显示的整数(0-4294967295)
* @param len - 数字的位数
* @param size - ASCII字符大小
* 字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{
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+(size/2)*t,y,' ',size);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size/2)*t,y,temp+'0',size);
}
}
/**
* @brief 在指定位置显示一个字符串
* @param x - 0 - 127
* @param y - 0 - 7
* @param chr - 待显示的字符串指针
* @param size - ASCII字符大小
* 字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowString(uint8_t x,uint8_t y,char *chr,uint8_t size)
{
uint8_t j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j],size);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
/**
* @brief 在指定位置显示一个汉字
* @param x - 0 - 127
* @param y - 0 - 7
* @param no - 汉字在中文字库数组中的索引(下标)
* @note 中文字库在oledfont.h文件中的Hzk数组中,需要提前使用软件对汉字取模
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
uint8_t t,adder=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_Write_Dat(Hzk[2*no][t]);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_Write_Dat(Hzk[2*no+1][t]);
adder+=1;
}
}
/**
* @brief 在指定位置显示一幅图片
* @param x1,x2 - 0 - 127
* @param y1,y2 - 0 - 7(8表示全屏显示)
* @param BMP - 图片数组地址
* @note 图像数组BMP存放在bmp.h文件中
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint8_t BMP[])
{
uint16_t j=0;
uint8_t x,y;
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++)
{
OLED_Write_Dat(BMP[j++]);
}
}
}
/**
* @brief OLED初始化
*/
void OLED_Init(void)
{
HAL_Delay(500);
OLED_Write_Cmd(0xAE);//--display off
OLED_Write_Cmd(0x00);//---set low column address
OLED_Write_Cmd(0x10);//---set high column address
OLED_Write_Cmd(0x40);//--set start line address
OLED_Write_Cmd(0x81); // contract control
OLED_Write_Cmd(0xFF);//--128
OLED_Write_Cmd(0xA1);//set segment remap
OLED_Write_Cmd(0xC8);//Com scan direction
OLED_Write_Cmd(0xA6);//--normal / reverse
OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
OLED_Write_Cmd(0x3F);//--1/32 duty
OLED_Write_Cmd(0xD3);//-set display offset
OLED_Write_Cmd(0x00);//
OLED_Write_Cmd(0xD5);//set osc division
OLED_Write_Cmd(0x80);
OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
OLED_Write_Cmd(0xF1);//
OLED_Write_Cmd(0xDA);//set com pin configuartion
OLED_Write_Cmd(0x12);//
OLED_Write_Cmd(0xDB);//set Vcomh
OLED_Write_Cmd(0x40);//
OLED_Write_Cmd(0x20);
OLED_Write_Cmd(0x02);
OLED_Write_Cmd(0x8D);//set charge pump enable
OLED_Write_Cmd(0x14);//
OLED_Write_Cmd(0xA4);
OLED_Write_Cmd(0xA6);
OLED_Write_Cmd(0xAF);//--turn on oled panel
OLED_Clear();
OLED_Set_Pos(0,0);
}
第三步调试传感器。
#include "bsp_dht11.h"
#include "main.h"
int Read_Byte(void)
{
int i, temp=0;
for(i=0;i<8;i++)
{
while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin)==GPIO_PIN_RESET);/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/
/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
*/
delay_us(30); //延时x us 这个延时需要大于数据0持续的时间即可
if(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin)==GPIO_PIN_SET)/* x us后仍为高电平表示数据“1” */
{
/* 等待数据1的高电平结束 */
while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin)==GPIO_PIN_SET);
temp|=(uint8_t)(0x01<<(7-i));
}
else // x us后为低电平表示数据“0”
{
temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
}
}
return temp;
}
int Read_DHT11(void)
{
int flag;
HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_RESET);
delay_us(18000);//延时18ms
HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_SET);
delay_us(30); //延时30us
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DH11_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin) == 0)
{
while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin) == 0) ;/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin) == 1) ;/*轮询直到从机发出的 80us 高电平 标置信号结束*/
humi_int= Read_Byte();
humi_deci= Read_Byte();
temp_int= Read_Byte();
temp_deci= Read_Byte();
check_sum= Read_Byte(); /*读取数据*/
if(check_sum == humi_int + humi_deci + temp_int+ temp_deci)
flag = 1;
}
GPIO_InitStruct.Pin = DH11_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_SET);/*IO重新设置为输出*/
if (flag) return 1;/*数据正常*/
else return 0;
}
/********************************************************
*
* @file ds18b20.c
* @brief ds18b20驱动
* @author Mculover666
***************************************************/
#include "ds18b20.h"
#include <stdio.h>
#include "main.h"
void DS18B20_InPut_Mode(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void DS18B20_OutPut_Mode(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_SET);
}
static void DS18B20_Send_Reset_Single(void)
{
DS18B20_OutPut_Mode();
/* 拉低总线 480 - 960 us*/
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET);
delay_us(500);
/* 释放总线 15 - 60 us */
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);
delay_us(15);
}
/**
* @brief 检测DS18B20存在脉冲
* @param none
* @retval 0 DS18B20设备正常
* @retval 1 DS18B20设备响应复位信号失败
* @retval 2 DS18B20设备释放总线失败
*/
static uint8_t DS18B20_Check_Ready_Single(void)
{
uint8_t cnt = 0;
/* 1.检测存在脉冲 */
DS18B20_InPut_Mode();
//等待DS18B20 拉低总线 (60~240 us 响应复位信号)
while (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN) && cnt < 80) {
delay_us(1);
cnt++;
}
if (cnt > 80) {
return 1;
}
/* 2.检测DS18B20是否释放总线 */
cnt = 0;
DS18B20_InPut_Mode();
//判断DS18B20是否释放总线(60~240 us 响应复位信号之后会释放总线)
while ((!HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN)) && cnt<80) {
delay_us(1);
cnt++;
}
if (cnt > 80) {
return 2;
} else {
return 0;
}
}
/**
* @brief 检测DS18B20设备是否正常
* @param none
* @retval 0 DS18B20设备正常
* @retval 1 DS18B20设备响应复位信号失败
* @retval 2 DS18B20设备释放总线失败
*/
static uint8_t DS18B20_Check_Device(void)
{
/*1.主机发送复位信号*/
DS18B20_Send_Reset_Single();
/*2.检测存在脉冲*/
return DS18B20_Check_Ready_Single();
}
/**
* @brief DS18B20初始化
* @param none
* @retval none
*/
void DS18B20_Init(void)
{
/* 1.DS18B20控制引脚初始化 */
//在main函数中已经初始化,不需要再次重复。
/*2.检测DS18B20设备是否正常*/
switch (DS18B20_Check_Device()) {
case 0:
//printf("DS18B20_Init OK!\n");
break;
case 1:
//printf("DS18B20no find\n");
break;
case 2:
//printf("DS18B20alway on\n");
break;
}
}
/**
* @brief 向DS18B20写一个字节
* @param cmd 要写入的字节
* @retval none
*/
static uint8_t DS18B20_Write_Byte(uint8_t cmd)
{
uint8_t i = 0;
/* 1. 设置总线为输出模式 */
DS18B20_OutPut_Mode();
/* 2. 发送数据,低位在前 */
for (i = 0; i < 8; i++) {
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET);
delay_us(2);
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,cmd & 0x01);
delay_us(60);
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);;
cmd >>= 1;
delay_us(2);
}
return 0;
}
/**
* @brief 从DS18B20读一个字节
* @param none
* @retval 读取到的一个字节数据
*/
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i = 0;
uint8_t data = 0;
/* 读取数据 */
for (i =0; i < 8; i++) {
DS18B20_OutPut_Mode();
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET);
delay_us(2);
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);
DS18B20_InPut_Mode();
delay_us(10);
data >>= 1 ;
if (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN) ) {
data |= 0x80;
}
delay_us(60);
DS18B20_OutPut_Mode();
HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);
}
return data;
}
/**
* @brief 从DS18B20读取一次数据
* @param none
* @retval 读取到的温度数据
* @note 适用于总线上只有一个DS18B20的情况
*/
void DS18B20_Read_Temperature(void)
{
uint16_t temp = 0;
uint8_t temp_H, temp_L;
DS18B20_Check_Device();
DS18B20_Write_Byte(0xCC); //跳过ROM序列检测
DS18B20_Write_Byte(0x44); //启动一次温度转换
//等待温度转换完成
while (DS18B20_Read_Byte() != 0xFF);
DS18B20_Check_Device(); //必须,不能省略
DS18B20_Write_Byte(0xCC); //跳过ROM序列检测
DS18B20_Write_Byte(0xBE); //读取温度
temp_L = DS18B20_Read_Byte(); //读取的温度低位数据
temp_H = DS18B20_Read_Byte(); //读取的温度高位数据
temp = temp_L | (temp_H << 8); //合成温度
ds18_int = temp >> 4 ; /*合成实际温度整数部分****精度相对上面的更高*/
ds18_deci = temp & 0xF ; /*合成实际温度小数部分*/
}
再加上eeprom
/**
* @Copyright (c) 2019,mculover666 All rights reserved
* @filename at24C02_i2c_drv.c
* @breif Drive AT24C02(EEPROM) based on stm32 iic peripheral
* @changelog v1.0 mculover666 2019/7/15
* v1.1 mculover666 2021/4/15 (add WRITE_CYCLE_TIME_MS)
* v1.2 mculover666 2021/4/28 (add value operation)
*/
#include "AT24C02_i2c_drv.h"
#include "i2c.h"
#include "main.h"
/**
* @brief write a byte to any address
* @param[in] addr address to write
* @param[in] data the pointer of data to write
* @return errcode
* @retval 0 success
* @retval -1 fail
*/
int AT24C02_Write_Byte(uint16_t addr, uint8_t* dat)
{
int ret;
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, 1, 100);
return ret == HAL_OK ? 0 : -1;
}
/**
* @brief read a byte from any address
* @param[in] addr address to rad
* @param[out] read_buf the pointer of buffer to save read data
* @return errcode
* @retval 0 success
* @retval -1 fail
*/
int AT24C02_Read_Byte(uint16_t addr, uint8_t* read_buf)
{
int ret;
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Read(&hi2c1, AT24C02_ADDR_READ, addr, I2C_MEMADD_SIZE_8BIT, read_buf, 1, 100);
return ret == HAL_OK ? 0 : -1;
}
/**
* @brief write amount bytes to any address
* @param[in] addr address to write
* @param[in] data the pointer of data buffer to write
* @return errcode
* @retval 0 success
* @retval else fail
*/
int AT24C02_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size)
{
int ret;
uint16_t i = 0;
uint16_t cnt = 0;
uint16_t page = 0;
if (0 == addr % 8) { // whether the addr is the starting address of the page
if (size <= 8) { //whether the number of bytes to be written is less than one page
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, size, 100);
if (ret != HAL_OK) {
return -1;
}
} else {
page = size / 8;
for (i = 0;i < page; i++) {
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], 8, 100);
if (ret != HAL_OK) {
return -2;
}
addr += 8;
cnt += 8;
}
if (cnt < size) { //write remain bytes
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], size - cnt, 100);
if (ret != HAL_OK) {
return -3;
}
}
}
} else { //the address deviates from the starting page address
if (size <= (8 - addr % 8)) { //whether we can finish writing on this page
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, size, 100);
if (ret != HAL_OK) {
return -4;
}
} else { //can't finish on this page
//finish the page first
cnt += 8 - addr % 8;
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, cnt, 100);
if (ret != HAL_OK) {
return -5;
}
addr += cnt;
//loops to write the entire page of data
page = (size - cnt) / 8;
for (i = 0;i < page; i++) {
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], 8, 100);
if (ret != HAL_OK) {
return -6;
}
addr += 8;
cnt += 8;
}
if (cnt < size) { //write remain bytes
delay_us(WRITE_CYCLE_TIME_MS*1000);
ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], size - cnt, 100);
if (ret != HAL_OK) {
return -7;
}
}
}
}
return 0;
}
/**
* @brief read amount bytes from any address
* @param[in] addr address to read
* @param[out] read_buf the pointer of buffer to save read data
* @return errcode
* @retval 0 success
* @retval -1 fail
*/
int AT24C02_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size)
{
int ret;
delay_us(WRITE_CYCLE_TIME_MS*1000);
//HAL_Delay(WRITE_CYCLE_TIME_MS);
ret = HAL_I2C_Mem_Read(&hi2c1, AT24C02_ADDR_READ, addr, I2C_MEMADD_SIZE_8BIT, recv_buf, size, 100);
return ret == HAL_OK ? 0 : -1;
}
/**
* @brief write value to any address
* @param[in] addr address to write
* @param[in] ptr the pointer of value to write
* @return errcode
* @retval 0 success
* @retval else fail
*/
int AT24C02_Write_Value(uint16_t addr, void *ptr, uint16_t size)
{
int ret;
if (!ptr) {
return -1;
}
ret = AT24C02_Write_Amount_Byte(addr, (uint8_t*)ptr, size);
if (ret < 0) {
return ret;
}
return 0;
}
/**
* @brief read value from any address
* @param[in] addr address to write
* @param[in] ptr the pointer of value to read
* @return errcode
* @retval 0 success
* @retval else fail
*/
int AT24C02_Read_Value(uint16_t addr, void *ptr, uint16_t size)
{
int ret;
if (!ptr) {
return -1;
}
ret = AT24C02_Read_Amount_Byte(addr, (uint8_t*)ptr, size);
if (ret < 0) {
return ret;
}
return 0;
}
最后再加上亿点点代码,就完成了
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "oled.h"
#include "bmp.h"
#include "bsp_dht11.h"
#include "stm32f4xx_hal_uart.h"
#include "ds18b20.h"
#include "string.h"
#include "at24c02_i2c_drv.h"
/* 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 */
int htim5_Period =1000-1;//PWM频率
int htim5_Period0 = 1000-1;//PWM频率
int LED_Blue_FLAG = 0;//PWM频率
int page=0;//界面显示页数
int page0=0;//保存page的内容
int hour=23;//时间
int minute_T=5;
int minute_S=7;
int second_T=5;
int second_S=8;
int Key_User,Key_S1,Key_S2;//按键状态
int Work_State=1;//传感器状态
int Work_State0=1;//传感器状态
uint8_t period = 1;
uint8_t period0 = 1;//多少个周期发送一次
//串口缓冲区
uint8_t usart2_rxone[1];
uint8_t usart2_rxbuf[20];
int usart2_rxcounter;
//温湿度
int humi_int,humi_deci,temp_int,temp_deci,check_sum;
int ds18_int,ds18_deci;
int tem_max_int = 30;int tem_max_dec = 0;int tem_min_int = 20;int tem_min_dec = 0;
int hum_max_int = 80;int hum_max_dec = 0;int hum_min_int = 10;int hum_min_dec = 0;
//温湿度历史数据
uint8_t tem_hisbuf[20];
int tem_hisbuf_position = 0;
int tem_hisbuf_position0 = 0;
int tem_position= 0x10;
int tem_position0= 0x10;
int page0_userkey_flag ,page0_userkey_flag0,page2_userkey_flag ,page2_userkey_flag0;
uint8_t uart_Reply[]=" 13.2 , 50%, 15 - 20 , 15:23:51\r\n";
uint8_t uart_Reply_num[2]="00";
//eeprom数据
uint8_t write_dat = '2';
uint8_t recv_buf = 0;
/* 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 */
//串口重定向
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
void uart_call_back(void);//串口回传
void time_compute(void);//计算时间
void temp_compute(void);//计算温度
void delay_us(volatile uint32_t us);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//串口中断接收
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);//按键检测
void UART2_Handle(void);//串口2接收信息处理
void key_handle(void);//按键处理
void page_handle(void);//页面显示
//1S定时器中断作为心跳
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* tim_baseHandle)
{
// AT24C02_Write_Byte(10, &write_dat);
// delay_us(50000);
// AT24C02_Read_Byte(10,&recv_buf);
//HAL_UART_Transmit(&huart2,&recv_buf,sizeof(recv_buf),0xff);
if(tim_baseHandle->Instance == htim2.Instance)
{
if(page==4)
{
if(page0!=page)//位置初始化
{
page0 = page;
tem_position = tem_position0;
tem_hisbuf_position = tem_hisbuf_position0;
}
AT24C02_Write_Byte(tem_position, &temp_int);
tem_hisbuf_position++;
tem_position++;
delay_us(150000);
AT24C02_Write_Byte(tem_position, &temp_deci);
tem_position++;
tem_hisbuf_position++;
}
if (tem_position>0x10+20){tem_position = tem_position0;tem_hisbuf_position = tem_hisbuf_position0;}//溢出后从头开始
if(usart2_rxcounter>1)
{
UART2_Handle();
}
if(Work_State==1)
{
DS18B20_Read_Temperature();
Read_DHT11();
}
key_handle();//按键处理
time_compute();//计算时间
temp_compute();//计算温度
page_handle(); //界面显示
printf("AT+CIPSEND=0,3\r\n");
delay_us(2000);
printf("T%d",temp_int);
delay_us(5000);
printf("AT+CIPSEND=0,3\r\n");
delay_us(2000);
printf("M%d",humi_int);
delay_us(1000);
if(temp_int*10+temp_deci>tem_max_int*10+tem_max_dec)
{
HAL_GPIO_TogglePin(LED_Blue_GPIO_Port,LED_Blue_Pin);
HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
htim5_Period = 4000-1 ;
if(htim5_Period != htim5_Period0 )
{
HAL_TIM_PWM_Stop(&htim5,TIM_CHANNEL_2);
MX_TIM5_Init();
HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
}
htim5_Period0 = htim5_Period;
}
else if(temp_int*10+temp_deci<tem_min_int*10+tem_min_dec)
{
if(LED_Blue_FLAG == 0)
{
HAL_GPIO_TogglePin(LED_Blue_GPIO_Port,LED_Blue_Pin);
LED_Blue_FLAG = 2;
}
else
{
LED_Blue_FLAG--;
}
HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
htim5_Period = 1000-1 ;
if(htim5_Period != htim5_Period0 )
{
HAL_TIM_PWM_Stop(&htim5,TIM_CHANNEL_2);
MX_TIM5_Init();
HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
}
htim5_Period0 = htim5_Period;
}
else
{
HAL_TIM_PWM_Stop(&htim5,TIM_CHANNEL_2);
HAL_GPIO_WritePin(LED_Blue_GPIO_Port,LED_Blue_Pin,GPIO_PIN_RESET);
}
uart_call_back();//串口回传
HAL_GPIO_TogglePin(LED_Yellow_GPIO_Port,LED_Yellow_Pin);
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uart_Reply[5] = 0xA1;uart_Reply[6] = 0xE6;uart_Reply[16] = 0xA1;uart_Reply[17] = 0xE6;uart_Reply[22] = 0xA1;uart_Reply[23] = 0xE6;//写入摄氏度
/* 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_USART2_UART_Init();
MX_I2C1_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
MX_TIM5_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_TogglePin(OLED_nRST_GPIO_Port,OLED_nRST_Pin);//开启OLED
OLED_Init();
OLED_ShowString(0, 0, "Starting......", 16);
OLED_ShowString(0, 2, "Reading History Tempreture...", 16);
//读取at24历史记录
for(int i = 0 ; i < 9 ; i++)
{
AT24C02_Read_Byte(tem_position,&tem_hisbuf[tem_hisbuf_position]);
tem_hisbuf_position++;
tem_position++;
delay_us(200000);
AT24C02_Read_Byte(tem_position,&tem_hisbuf[tem_hisbuf_position]);
tem_hisbuf_position++;
tem_position++;
delay_us(200000);
}
tem_position = tem_position0;
tem_hisbuf_position = tem_hisbuf_position0 ;
HAL_Delay(1000);
OLED_ShowString(0, 6, "Opening wifi...", 16);
HAL_Delay(2000);
printf("AT+CWMODE=2\r\n");//##配置ESP8266模块为AP模式,开启wifi热点。
HAL_Delay(500);
printf("AT+RST\r\n");//##重启模块使AP模式生效
HAL_Delay(1000);
printf("AT+CIPMUX=1\r\n");//##启动多连接,id分配顺序是0-4。
HAL_Delay(500);
printf("AT+CIPSERVER=1,8080\r\n");//##模块开启服务器模式,端口号8080
HAL_Delay(500);
OLED_Clear();//初始化完成
HAL_TIM_Base_Start_IT(&htim2);//开启定时器2
HAL_UART_Receive_IT(&huart2,usart2_rxone,1);//开始串口中断
DS18B20_Init();//初始化温度传感器
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/*************************************END OF FILE******************************/
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 100;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void time_compute(void)
{
second_S++;
if (second_S>=10){second_S-=10;second_T++;}
if (second_T>=6){second_T-=6;minute_S++;}
if (minute_S>=10){minute_S-=10;minute_T++;}
if (minute_T>=6){minute_T-=6;hour++;}
if (hour>=24){hour-=24;}
}
void temp_compute(void)
{
if (tem_max_dec>=10){tem_max_dec=0;tem_max_int++;}
if (tem_min_dec>=10){tem_min_dec=0;tem_min_int++;}
if (tem_max_dec<0){tem_max_dec=5;tem_max_int--;}
if (tem_min_dec<0){tem_min_dec=5;tem_min_int--;}
if (tem_max_int>=100||tem_max_int<0){tem_max_int-=0;}
if (tem_min_int>=100||tem_min_int<0){tem_min_int-=0;}
if((tem_max_int*10+tem_max_dec)<(tem_min_int*10+tem_min_dec))
{
tem_max_int=tem_min_int;
tem_max_dec=tem_min_dec;
}
if((hum_max_int*10+hum_max_dec)<(hum_min_int*10+hum_min_dec))
{
hum_max_int=hum_min_int;
hum_max_dec=hum_min_dec;
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) // 判断是由哪个串口触发的中断
{
//将接收到的数据放入接收usart1接收数组
usart2_rxbuf[usart2_rxcounter] = usart2_rxone[0];
//HAL_UART_Transmit(&huart2,usart2_rxone,1,0xff);
usart2_rxcounter++; //接收数量+1
//重新使能串口1接收中断
HAL_UART_Receive_IT(&huart2,usart2_rxone,1);
}
}
void delay_us(volatile uint32_t us)
{
volatile uint16_t i,j;
while(us--)
{
for(i=0;i<6;i++)
j++;
}
}
void page_handle(void)
{
if(page0!=page) OLED_Clear();
page0 = page;
if(Work_State0!=Work_State) OLED_Clear();
Work_State0=Work_State;
if(page==0)//界面0时间显示页面
{
OLED_DrawBMP(0, 0, 64, 8,BMP1);
OLED_ShowString(64, 0, "Project2", 16);
OLED_ShowString(64, 2, "20221018", 16);
OLED_ShowString(64, 4, "Time", 16);
OLED_ShowChar(80,6,':',16);
OLED_ShowChar(104,6,':',16);
OLED_ShowNum(65,6,hour,2,16);
OLED_ShowNum(88,6,minute_T,1,16);
OLED_ShowNum(96,6,minute_S,1,16);
OLED_ShowNum(112,6,second_T,1,16);
OLED_ShowNum(120,6,second_S,1,16);
if(page0_userkey_flag!=0)
{
if(page0_userkey_flag0==page0_userkey_flag)
{
switch(page0_userkey_flag)
{
case 1: OLED_ShowString(65, 6, " ", 16);
break;
case 2: OLED_ShowString(88, 6, " ", 16);
break;
case 3: OLED_ShowString(96, 6, " ", 16);
break;
case 4: OLED_ShowString(112, 6, " ", 16);
break;
case 5: OLED_ShowString(120, 6, " ", 16);
break;
default: page0_userkey_flag=0;
break;
}
page0_userkey_flag0=6;
}
else page0_userkey_flag0--;
}
}
if(page==1)//界面1测量确认界面
{
if(Work_State == 1)
{
OLED_ShowString(0, 0, "Press User Key", 16);
OLED_ShowString(0, 2, "Start Work", 16);
OLED_ShowString(80, 2, "<===", 16);
OLED_ShowString(0, 4, "Long Press", 16);
OLED_ShowString(0, 6, "Stop Work", 16);
}
else{
OLED_ShowString(0, 0, "Press User Key", 16);
OLED_ShowString(0, 2, "Start Work", 16);
OLED_ShowString(0, 4, "Long Press", 16);
OLED_ShowString(0, 6, "Stop Work", 16);
OLED_ShowString(80, 6, "<===", 16);
}
}
if(page==2)//界面1
{
if(Work_State == 1)
{
//第一列信息
OLED_ShowString(0, 0, "DH11|", 16);
OLED_ShowString(0, 2, " |", 16);
OLED_ShowString(0, 4, "DS18|", 16);
OLED_ShowString(0, 6, "Limt|", 16);
//第二列温湿度
OLED_ShowNum(44,0,temp_int,2,16);
OLED_ShowNum(70,0,temp_deci,1,16);
OLED_ShowString(62, 0, ".", 16);
OLED_ShowString(84, 0, "Cels", 16);
OLED_ShowNum(44,2,humi_int,2,16);
OLED_ShowNum(70,2,humi_deci,1,16);
OLED_ShowString(62, 2, ".", 16);
OLED_ShowString(84, 2, "%", 16);
OLED_ShowNum(44,4,ds18_int,2,16);
OLED_ShowNum(70,4,ds18_deci,1,16);
OLED_ShowString(84, 4, "Cels", 16);
OLED_ShowString(62, 4, ".", 16);
//范围
OLED_ShowNum(44,6,tem_max_int,2,16);
OLED_ShowNum(70,6,tem_max_dec,1,16);
OLED_ShowString(62, 6, ".", 16);
OLED_ShowNum(84,6,tem_min_int,2,16);
OLED_ShowNum(108,6,tem_min_dec,1,16);
OLED_ShowString(100, 6, ".", 16);
}
else{
//第一列信息
//第一列信息
OLED_ShowString(0, 0, "DH11|", 16);
OLED_ShowString(0, 2, " |", 16);
OLED_ShowString(0, 4, "DS18|", 16);
OLED_ShowString(0, 6, "Limt|", 16);
//第二列温湿度
OLED_ShowString(60, 0, "None", 16);
OLED_ShowString(60, 2, "None", 16);
OLED_ShowString(60, 4, "None", 16);
//范围
OLED_ShowNum(44,6,tem_max_int,2,16);
OLED_ShowNum(70,6,tem_max_dec,1,16);
OLED_ShowString(62, 6, ".", 16);
OLED_ShowNum(84,6,tem_min_int,2,16);
OLED_ShowNum(108,6,tem_min_dec,1,16);
OLED_ShowString(100, 6, ".", 16);
}
if(page2_userkey_flag!=0)//闪烁位置
{
if(page2_userkey_flag0 == page2_userkey_flag)
{
switch(page2_userkey_flag)
{
case 1: OLED_ShowString(44, 6, " ", 16);
break;
case 2: OLED_ShowString(70, 6, " ", 16);
break;
case 3: OLED_ShowString(84, 6, " ", 16);
break;
case 4: OLED_ShowString(108,6, " ", 16);
break;
default: page0_userkey_flag=0;
break;
}
page2_userkey_flag0=5;
}
else page2_userkey_flag0--;
}
}
//
//uint8_t tem_int_hisbuf[9];
//int tem_int_position= 0x10;
//int tem_int_position0= 0x10;
//uint8_t tem_dec_hisbuf[9];
//int tem_dec_position= 0x20;
//int tem_dec_position0= 0x20;
if(page==3)
{
tem_hisbuf_position = 0;
OLED_ShowString(0, 0, "Tem History:", 16);
OLED_ShowString(16, 2, ".", 16);
OLED_ShowNum(0,2,tem_hisbuf[tem_hisbuf_position],2,16);
tem_hisbuf_position++;
OLED_ShowNum(24,2,tem_hisbuf[tem_hisbuf_position],1,16);
tem_hisbuf_position++;
OLED_ShowNum(48,2,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(72,2,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(64, 2, ".", 16);
OLED_ShowNum(96,2,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(120,2,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(112, 2, ".", 16);
OLED_ShowNum(0,4,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(24,4,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(16, 4, ".", 16);
OLED_ShowNum(48,4,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(72,4,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(64, 4, ".", 16);
OLED_ShowNum(96,4,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(120,4,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(112, 4, ".", 16);
OLED_ShowNum(0,6,tem_hisbuf[tem_hisbuf_position],2,16); tem_hisbuf_position++;
OLED_ShowNum(24,6,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(16, 6, ".", 16);
OLED_ShowNum(48,6,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(72,6,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;
OLED_ShowString(64, 6, ".", 16);
OLED_ShowNum(96,6,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;
OLED_ShowNum(120,6,tem_hisbuf[tem_hisbuf_position],1,16); tem_hisbuf_position++;
OLED_ShowString(112, 6, ".", 16);
}
if(page==4)
{
OLED_ShowString(0, 0, "Writing Tem", 16);
OLED_ShowString(0, 2, "Recording...", 16);
OLED_ShowString(0, 4, "Tem Data", 16);
OLED_ShowNum(100,4,temp_deci,1,16);
OLED_ShowString(92, 4, ".", 16);
OLED_ShowNum(76,4,temp_int,2,16);
}
if(page<0)
{
OLED_Clear();
page = 0;
}
if(page>4)
{
OLED_Clear();
page = 4;
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* 判断哪个引脚触发了中断 */
switch(GPIO_Pin)
{
case S1_Pin:
/* 处理S1_Pin:发生的中断 */
delay_us(10);//按键消抖
if(1 == HAL_GPIO_ReadPin(S1_GPIO_Port,S1_Pin))
{
Key_S1=1;
}
break;
case S2_Pin:
/* 处理GPIO3发生的中断 */
delay_us(10);//按键消抖
if(1 == HAL_GPIO_ReadPin(S2_GPIO_Port,S2_Pin))
{
Key_S2=1;
}
break;
case User_Key_Pin:
/* 处理User_Key发生的中断 */
delay_us(10);//按键消抖
if(0 == HAL_GPIO_ReadPin(User_Key_GPIO_Port,User_Key_Pin))
{
Key_User = 1;//短按
}
default:
break;
}
}
//按键处理
void key_handle(void)
{
if(Key_S1 == 1)
{
Key_S1 = 0;
if(page0_userkey_flag!=0)
{
switch(page0_userkey_flag)
{
case 1: hour--;
break;
case 2: minute_T--;
break;
case 3: minute_S--;
break;
case 4: second_T--;
break;
case 5: second_S--;
break;
default: page0_userkey_flag=0;
break;
}
}
else if(page2_userkey_flag!=0)
{
switch(page2_userkey_flag)
{
case 1: tem_max_int-=5;
break;
case 2: tem_max_dec-=5;
break;
case 3: tem_min_int-=5;
break;
case 4: tem_min_dec-=5;
break;
default: page0_userkey_flag=0;
break;
}
}
else page++;
}
if(Key_S2 == 1)
{
Key_S2 = 0;
if(page0_userkey_flag!=0)
{
switch(page0_userkey_flag)
{
case 1: hour++;
break;
case 2: minute_T++;
break;
case 3: minute_S++;
break;
case 4: second_T++;
break;
case 5: second_S++;
break;
default: page0_userkey_flag=0;
break;
}
}
else if(page2_userkey_flag!=0)
{
switch(page2_userkey_flag)
{
case 1: tem_max_int+=5;
break;
case 2: tem_max_dec+=5;
break;
case 3: tem_min_int+=5;
break;
case 4: tem_min_dec+=5;
break;
default: page0_userkey_flag=0;
break;
}
}
else page--;
}
if(Key_User == 1)
{
if(page == 0)
{
page0_userkey_flag++;
if(page0_userkey_flag>5) {page0_userkey_flag=0;}
page0_userkey_flag0 = page0_userkey_flag;
}
if(page == 1)
{
if(Work_State ==0) Work_State=1;
else if(Work_State ==1) Work_State=0;
}
if(page == 2)
{
page2_userkey_flag++;
if(page2_userkey_flag>4) {page2_userkey_flag=0;}
page2_userkey_flag0 = page2_userkey_flag;
}
Key_User = 0;
}
}
//串口2接收信息处理
void UART2_Handle(void)
{
uint8_t start_buf[13] = "START_TEM";
uint8_t stop_buf[13] = "STOP_TEM";
uint8_t start_Reply[] = "Start the temperature and humidity measure\r\n";
uint8_t stop_Reply[] = "Close the temperature and humidity measure\r\n";
uint8_t period_Reply1[] = "Data will up load every ";
uint8_t period_Reply2[] = " period\r\n";
uint8_t tem_l_Reply[] = " is set as the limits of lower temperature\r\n";
uint8_t tem_h_Reply[] = " is set as the limits of upper temperature\r\n";
uint8_t time_Reply[] = "New time have been set as ";
uint8_t bank_Reply[] = "\r\n";
if(strcmp(usart2_rxbuf,start_buf)==0){Work_State=1;HAL_UART_Transmit(&huart2,start_Reply,sizeof(start_Reply),0xff);}
if(strcmp(usart2_rxbuf,stop_buf)==0){Work_State=0;HAL_UART_Transmit(&huart2,stop_Reply,sizeof(start_Reply),0xff);}
if(usart2_rxbuf[0]=='T')
{
if(usart2_rxbuf[1]=='=')
{
period = usart2_rxbuf[2]-'0';
period0 = period;
HAL_UART_Transmit(&huart2,period_Reply1,sizeof(period_Reply1),0xff);
HAL_UART_Transmit(&huart2,&usart2_rxbuf[2],1,0xff);
HAL_UART_Transmit(&huart2,period_Reply2,sizeof(period_Reply2),0xff);
}
if(usart2_rxbuf[1]=='E')
{
if(usart2_rxbuf[4]=='L')
{
tem_min_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';//TEM_L=xx.x
tem_min_dec = usart2_rxbuf[9]-'0';
HAL_UART_Transmit(&huart2,&usart2_rxbuf[6],4,0xff);
HAL_UART_Transmit(&huart2,tem_l_Reply,sizeof(tem_l_Reply),0xff);
}
if(usart2_rxbuf[4]=='H')
{
tem_max_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';//TEM_H=xx.x
tem_max_dec = usart2_rxbuf[9]-'0';
HAL_UART_Transmit(&huart2,&usart2_rxbuf[6],4,0xff);
HAL_UART_Transmit(&huart2,tem_h_Reply,sizeof(tem_h_Reply),0xff);
}
}
if(usart2_rxbuf[1]=='I')
{
hour = (usart2_rxbuf[5]-'0')*10+usart2_rxbuf[6]-'0';//TIME=hh:mm:ss
minute_T=usart2_rxbuf[8]-'0';
minute_S=usart2_rxbuf[9]-'0';
second_T=usart2_rxbuf[11]-'0';
second_S=usart2_rxbuf[12]-'0';
HAL_UART_Transmit(&huart2,time_Reply,sizeof(time_Reply),0xff);
HAL_UART_Transmit(&huart2,&usart2_rxbuf[5],8,0xff);
HAL_UART_Transmit(&huart2,bank_Reply,sizeof(bank_Reply),0xff);
}
}
if(usart2_rxbuf[0]=='H')
{
if(usart2_rxbuf[4]=='L')
{
hum_min_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';//HUM_L=xx.x(%)
hum_min_dec = usart2_rxbuf[9]-'0';
}
if(usart2_rxbuf[4]=='H')
{
hum_max_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';
hum_max_dec = usart2_rxbuf[9]-'0';
}
}
usart2_rxcounter=0;
memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));
}
//串口回传
void uart_call_back(void)
{
uint8_t uart_BReply[]="(";
uint8_t uart_CReply[]=")";
uint8_t uart_workstate_Reply[]="sensor stop work, send history data\t";
if(period0 <= 1)
{
if(Work_State == 0)
{
HAL_UART_Transmit(&huart2,uart_workstate_Reply,sizeof(uart_workstate_Reply),0xff);
}
HAL_UART_Transmit(&huart2,uart_BReply,1,0xff);
if(uart_Reply_num[1]<'9')
{uart_Reply_num[1]=uart_Reply_num[1]+1;}
else
{uart_Reply_num[1]='0';uart_Reply_num[0]=uart_Reply_num[0]+1;}
if(uart_Reply_num[0]>'9') uart_Reply_num[0]='0';
HAL_UART_Transmit(&huart2,uart_Reply_num,2,0xff);
HAL_UART_Transmit(&huart2,uart_CReply,1,0xff);
uart_Reply[1]='0'+temp_int/10;
uart_Reply[2]='0'+temp_int%10;
uart_Reply[4]='0'+temp_deci;
uart_Reply[9]='0'+humi_int/10;
uart_Reply[10]='0'+humi_int%10;
uart_Reply[14]='0'+tem_min_int/10;
uart_Reply[15]='0'+tem_min_int%10;
uart_Reply[20]='0'+tem_max_int/10;
uart_Reply[21]='0'+tem_max_int%10;
uart_Reply[26]='0'+hour/10;
uart_Reply[27]='0'+hour%10;
uart_Reply[29]='0'+minute_T;
uart_Reply[30]='0'+minute_S;
uart_Reply[32]='0'+second_T;
uart_Reply[33]='0'+second_S;
HAL_UART_Transmit(&huart2,uart_Reply,sizeof(uart_Reply),0xff);
period0 = period;
}
else period0--;
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */