最近在准备蓝桥杯,写了一个垃圾的小程序,算是比较综合的程序了,大家有什么好的想法我也可以试试,欢迎大家提问!!
最后有工程链接!!!
最后有工程链接!!!
最后有工程链接!!!
使用的是STM32G431RB单片机,hal库配置,把基本的配置都加进去了
主要外设:
LED,ADC,RTC,IIC,串口
主要功能都集中在按键和串口
1、按键可以识别单击、双击、长按、短按、并且获取键值,内部结构体还可以获取上一次键值,按键按下间隔时间,按键按下时间
2、串口使用不定长数据接收,暂时还没有做更多功能,不定长使用的是定时器中断查询方式,没有使用串口空闲中断,(就是太垃圾)但是用起来效果还可以。
开放工程大家一起学习,代码哪里有问题的欢迎指正。
贴一下主要代码:
#include "user_app.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
uint8_t buffer[1]; //串口接收缓存
int frequency_tim2=0; //定时器2频率
int frequency_tim3=0; //定时器3频率
float zkb1=0.00; //定时器3占空比
float zkb2=0.00; //定时器4占空比
RTC_TimeTypeDef time; //当前时间(在sys中断中调用)
RTC_DateTypeDef data; //当前日期(在sys中断中调用)
uint16_t delay_time=0; //计算按键按下时长
uint32_t delay_ms_sign=0; //计算按键按下间隔时长
//按键结构体
typedef struct key
{
uint16_t key_time; //按键按下时间
uint8_t key_count; //按键计数
uint16_t time_lag; //两次按键的时间间隔
uint8_t last_key_data; //记住上一次键值
_Bool double_key; //0表示单击,1表示双击
_Bool long_press; //0表示短按,1表示长按
void (*get_data)(uint8_t *kdata); //函数指针指向获取按键函数
}KEY;
static KEY key1; //创建一个KEY类型数据
/*============================================
*
* user_main : 用户主函数
*
============================================*/
void user_main(void)
{
char *pf;
pf=malloc(20); //申请显示内存
uint8_t key=15; //存储的按键值
key1.key_time=0; //初始按键按下时间
key1.get_data=get_key; //函数指针指向获取按键值的函数
key1.time_lag=0; //初始按键间隔时间
key1.double_key=0; //初始为单击
key1.last_key_data=0; //初始上一次按键值
user_init(); //用户初始化
while(1)
{
sprintf(pf,"frequency1:%dHZ ",frequency_tim3);
LCD_DisplayStringLine(Line3,(uint8_t *)pf);
sprintf(pf,"frequency2:%dHZ ",frequency_tim2);
LCD_DisplayStringLine(Line4,(uint8_t *)pf);
sprintf(pf,"frequency1:%.2f ",zkb1);
LCD_DisplayStringLine(Line5,(uint8_t *)pf);
sprintf(pf,"frequency2:%.2f",zkb2);
LCD_DisplayStringLine(Line6,(uint8_t *)pf);
sprintf(pf,"time:%02d:%02d:%02d",time.Hours,time.Minutes,time.Seconds);
LCD_DisplayStringLine(Line7,(uint8_t *)pf);
sprintf(pf,"Starting up count:%d",read_at24c02(0));
LCD_DisplayStringLine(Line8,(uint8_t *)pf);
key1.get_data(&key); //获取按键值
if((key1.time_lag<500)&&(key1.last_key_data==key))//判断按键间隔时间是否小于500,而且与上一次键值相等
{
key1.double_key=1;//双击
}
else
{
key1.double_key=0;//单击
}
if(key1.key_time >350)//按键按下时间是否大于400
{
key1.long_press=1;//长按
}
else
{
key1.long_press=0;//短按
}
if(key!=15)
{
LCD_ClearLine(Line9);
sprintf(pf,"K:%d long:%d double:%d",key,key1.long_press,key1.double_key);
LCD_DisplayStringLine(Line9,(uint8_t *)pf);
}
ADC_test(pf,&hadc1,Line1,5);
ADC_test(pf,&hadc2,Line2,5);
}
}
/*============================================
*
* user_init : 用户初始化函数
*
============================================*/
void user_init(void)
{
char *pf;
pf=malloc(20);
RTC_TimeTypeDef set_time; //定义当前时间
set_time.Hours=17; //设置小时
set_time.Minutes=37; //设置分钟
set_time.Seconds=00; //设置秒
uint8_t start_up_count=0; //存储开机次数
I2CInit(); //IIC初始化
start_up_count=read_at24c02(0); //读取开机次数
write_at24c02(0,++start_up_count); //写入开机次数
HAL_UART_Receive_IT(&huart1,buffer,1); //打开串口接收中断
HAL_RTC_SetTime(&hrtc,&set_time,RTC_FORMAT_BIN); //设置当前时间
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //打开定时器输入中断
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2); //打开定时器输入中断
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1); //打开定时器输入中断
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2); //打开定时器输入中断
LCD_Init(); //lcd初始化
HAL_UART_Transmit(&huart1,(uint8_t *)"串口初始化完成!!!\r\n请输入数据\r\n",sizeof("串口初始化完成!!!\r\n请输入数据\r\n"),100);
LCD_Clear(White);
LCD_SetBackColor(White);
LCD_SetTextColor(Red);
LCD_DisplayStringLine(Line0,(uint8_t *)" COMPREHENSIVE ");
// HAL_ADC_Start(&hadc1);//打开ADC1转换
// HAL_ADC_Start(&hadc2);//打开ADC2转换
//
// ADC_test(pf,&hadc1,Line1 ,100);//ADC测试
// ADC_test(pf,&hadc2,Line2 ,100);
led_test(3,200); //LED测试
}
/*============================================
*
* led_test : led测试函数
*
* num : 闪烁次数,为奇数时最后关闭led;
* delay_ms : 延时时间(闪烁间隔时间)
*
============================================*/
void led_test(uint8_t num,uint16_t delay_ms)
{
for(uint8_t i=0;i<num;i++)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_All);
led_refresh();
HAL_Delay(delay_ms);
}
}
/*============================================
*
* led_test : led刷新函数
*
============================================*/
void led_refresh(void)
{
LED_START;
LED_STOP;
}
/*============================================
*
* ADC_test : ADC测试函数
*
* pf : 打印内存存储空间;
* hadcx : 延时时间
* dsp_line : 打印行数
* delay_ms : 打印延时
*
============================================*/
void ADC_test(char *pf,ADC_HandleTypeDef *hadcx,uint8_t dsp_line,uint16_t delay_ms)
{
float adc_value=0;
HAL_ADC_Start(hadcx);
adc_value=HAL_ADC_GetValue(hadcx)*3;
if(hadcx->Instance==ADC2)
{
sprintf(pf," ADC2:%.2f V ",adc_value/4095);
}
else
{
sprintf(pf," ADC1:%.2f V ",adc_value/4095);
}
LCD_DisplayStringLine(dsp_line,(uint8_t *)pf);
HAL_Delay(delay_ms);
}
/*============================================
*
* HAL_UART_RxCpltCallback : 串口回调函数
*
============================================*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_IT(&huart1,buffer,1);//重新打开串口接受中断
}
/*============================================
*
* HAL_TIM_IC_CaptureCallback : 定时器输入回调函数
*
============================================*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
float tim2_ch1=0,tim2_ch2=0;//必须定义为float类型才能被运算
float tim3_ch1=0,tim3_ch2=0;//必须定义为float类型才能被运算
if(htim->Instance==TIM2)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)//确定转换通道,不然两个通道都会进入获取
{
tim2_ch1=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取转换周期
tim2_ch2=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);//获取低电平时间
__HAL_TIM_SetCounter(&htim2,0);//清楚定时器计数
frequency_tim2=1000000/tim2_ch1;//计算频率
zkb2=(float)(tim2_ch2/tim2_ch1)*100;//计算占空比
}
}
if(htim->Instance==TIM3)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
{
tim3_ch1=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
tim3_ch2=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
frequency_tim3=1000000/tim3_ch1;
zkb1=(tim3_ch2/tim3_ch1)*100;
__HAL_TIM_SetCounter(&htim3,0);
}
}
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//重新打开定时器输入转换
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
}
/*============================================
*
* read_at24c02 : 24c02读取函数
*
* add : 读取地址;
*
============================================*/
uint8_t read_at24c02(uint8_t add)
{
uint8_t data;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
data=I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return data;
}
/*============================================
*
* write_at24c02 : 24c02写入数据函数
*
* add : 写入地址;
* data : 写入数据
*
============================================*/
void write_at24c02(uint8_t add,uint8_t data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
///*============================================
//*
//* write_at24c02 : 24c02写入数据函数
//*
//* add : 写入地址;
//* data : 写入数据
//* 我需要返回按键的次数
//* 按键的按下的时间
//* 按下的键值
//*
//============================================*/
//uint8_t get_key(void)
//{
// uint8_t key_data=0;
// if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
// {
if(delay_sign(5))
{
// if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
// {
//
while((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15)
{
//
// switch((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07)))
// {
// case 14 : key_data=1;break;
// case 13 : key_data=2;break;
// case 11 : key_data=3;break;
// case 07 : key_data=4;break;
// default : return key_data;
// }
}
}
// }
// }
// return key_data;
//}
/*============================================
*
* write_at24c02 : 24c02写入数据函数
*
* add : 写入地址;
* data : 写入数据
* 我需要返回按键的次数
* 按键的按下的时间
* 按下的键值
*
============================================*/
void get_key( uint8_t *key_data)
{
static uint8_t keydata=0;//保存键值
if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
{
HAL_Delay(5);
if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
{
key1.last_key_data=keydata;//将保存的上一次键值付给结构体
key1.time_lag= delay_ms_sign;
delay_time=0;
delay_ms_sign=0;
while((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15)
{
switch((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07)))
{
case 14 : *key_data=1; keydata=1;break;
case 13 : *key_data=2; keydata=2;break;
case 11 : *key_data=3; keydata=3;break;
case 07 : *key_data=4; keydata=4;break;
default : *key_data=*key_data; break;
}
}
key1.key_time=delay_time;
key1.key_count++;
}
}
}
//_Bool delay_sign(uint16_t delay)
//{
// delay_mark=1;
// if(delay<delay_time)
// {
// delay_mark=0;
// delay_time=0;
// return 1;
// }
// else
// {
// return 0;
// }
//}
//uint8_t dblclick(uint8_t key)
//{
//
// if(key == get_key())
// {
//
// }
//}
//typedef struct keydata
//{
// KEY KEYdata;
// KEYdata.key
// uint16_t key_time;
// uint8_t key_count;
//}KEYDATA;
//void key_data_init()
//{
//}
收都收了,麻烦点个赞吧!!!
链接:https://pan.baidu.com/s/1cvUvt_tgbyGyj8Jci5_qxw?pwd=wcj7
提取码:wcj7