目录
系列文章目录
往期文章:
第十一届
第十五届4T模拟赛加更新版
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
一、程序设计题目介绍
二、cubemx主要配置
1.定时器配置
普通定时器TIM2,这里我是用作pwm的输出
普通定时器TIM3,这里我是用作计时0.1s
普通定时器TIM4,这里我是用来按键消抖的
(PS:下面的几张图片分别是TIM2,TIM3,TIM4的配置,这次没有全屏截图了,李姐一下哈)
2.串口配置
串口这里需要注意的是一定要打开接收和发送的引脚,这里我用的是USART1,所以处理好PA9,PA10的引脚
3.LED,按键配置
三、程序模块代码编写
1.LED模块
#include "led.h"
//控制所有LED灯亮灭
void Contro_Led(unsigned char state)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, state);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
//控制单个LED灯的亮灭
void Contro_One_Led(unsigned char location,unsigned char state)
{
HAL_GPIO_WritePin(GPIOC,location<<8,state);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
LED综合使用函数:
void Display_led()
{
if(is_correct==1)
{
//LED1亮5秒后熄灭
count=0;
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
Contro_One_Led(0x01,0);
HAL_TIM_Base_Start_IT(&htim3);
}
else if(is_correct==0 && error_counts>=3)
{
// LED2每隔0.1秒切换亮灭,保持5秒钟
count=0;
led2_sta=1;
//这里同样是解决LCD,LED显示冲突的一个小处理
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
Contro_One_Led(0x02,led2_sta);
//从这里打开定时器3,避免时间上有误差
HAL_TIM_Base_Start_IT(&htim3);
}
}
//串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
RXbuff[BufIndex++]=Rxdat;
HAL_UART_Receive_IT(&huart1, &Rxdat, 1);
}
}
2.按键模块
/**************************定时器回调函数******************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
keys[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(unsigned char i=0;i<4;i++)
{
switch(keys[i].key_pro)
{
case 0:
{
if(keys[i].key_sta==0)
keys[i].key_pro=1;
}
break;
case 1:
{
if(keys[i].key_sta==0)
keys[i].key_pro=2;
else
keys[i].key_pro=0;
}
break;
case 2:
{
if(keys[i].key_sta==1)
{
keys[i].key_flg=1;
keys[i].key_pro=0;
}
}
break;
}
}
}
if(htim->Instance==TIM3)
{
count++;
//密码输入正确,LED1点亮5s后熄灭
//改变PWM的输出频率,占空比
if(is_correct==1 && count==50)
{
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
Contro_One_Led(0x01,1);
htim2.Init.Prescaler = 80-1;
htim2.Init.Period = 999;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,500);
duty=50;
freq=1000;
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_Base_Stop(&htim3);
}
//密码输入错误次数到三次以上,LED2在5s内每隔0.1s切换状态
if(is_correct==0 && error_counts>=3)
{
if(count!=50)
{
//这里为了避免LED和LCD发生冲突,所以在LED亮灭前进行了处理
//前面的更新文章里面有提到,需要的话可以去看看
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
led2_sta=led2_sta^1;
Contro_One_Led(0x02,led2_sta);
}
else
{
HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
Contro_One_Led(0x02,1);
//这里在5s之后关闭定时器,以防后面计时错误
HAL_TIM_Base_Stop(&htim3);
}
}
}
}
3.LCD模块
/**********************LCD模块********************/
// 密码输入界面显示
void Disp_Code_Enter()
{
sprintf(st," PSD ");
LCD_DisplayStringLine(Line1,(u8*)st);
if(code_1==-1)
{
sprintf(st," B1:@ ");
LCD_DisplayStringLine(Line3,(u8*)st);
}
else
{
sprintf(st," B1:%d ",code_1);
LCD_DisplayStringLine(Line3,(u8*)st);
}
if(code_2==-1)
{
sprintf(st," B2:@ ");
LCD_DisplayStringLine(Line4,(u8*)st);
}
else
{
sprintf(st," B2:%d ",code_2);
LCD_DisplayStringLine(Line4,(u8*)st);
}
if(code_3==-1)
{
sprintf(st," B3:@ ");
LCD_DisplayStringLine(Line5,(u8*)st);
}
else
{
sprintf(st," B3:%d ",code_3);
LCD_DisplayStringLine(Line5,(u8*)st);
}
}
// 参数界面显示
void Disp_Para()
{
sprintf(st," STA ");
LCD_DisplayStringLine(Line1,(u8*)st);
sprintf(st," F:%dHz ",freq);
LCD_DisplayStringLine(Line3,(u8*)st);
sprintf(st," D:%d%% ",duty);
LCD_DisplayStringLine(Line4,(u8*)st);
sprintf(st," ");
LCD_DisplayStringLine(Line5,(u8*)st);
}
//LCD综合使用函数
void Display_lcd(uint8_t menu)
{
if(menu==0)
Disp_Code_Enter();
else
Disp_Para();
}
4.串口模块
/************************串口模块****************************/
//串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
RXbuff[BufIndex++]=Rxdat;
HAL_UART_Receive_IT(&huart1, &Rxdat, 1);
}
}
//串口接收数据处理函数
void GetData_uart()
{
//判断是否收到数据
if(BufIndex<=6)
return ;
//判断接收到数据是否符合要求
if(RXbuff[0]-48==code_one && RXbuff[1]-48==code_two && RXbuff[2]-48==code_thr && RXbuff[3]=='-')
{
if(RXbuff[4]-48==code_one && RXbuff[5]-48==code_two && RXbuff[6]-48==code_thr)
return ;
else
{
code_one=RXbuff[4]-48;
code_two=RXbuff[5]-48;
code_thr=RXbuff[6]-48;
BufIndex=0;
sprintf(TXbuff,"success\r\n");
HAL_UART_Transmit_IT(&huart1, (u8*)TXbuff, sizeof(TXbuff));
}
}
else
return ;
}
5.其他函数模块
void Key_Function()
{
if(keys[0].key_flg==1)
{
//对密码第一位进行更新数值
code_1++;
if(code_1==10)
code_1=0;
keys[0].key_flg=0;
}
if(keys[1].key_flg==1)
{
//对密码第二位进行更新数值
code_2++;
if(code_2==10)
code_2=0;
keys[1].key_flg=0;
}
if(keys[2].key_flg==1)
{
//对密码第三位进行更新数值
code_3++;
if(code_3==10)
code_3=0;
keys[2].key_flg=0;
}
if(keys[3].key_flg==1)
{
//密码输入正确
if(code_1==code_one && code_2==code_two && code_3==code_thr)
{
is_correct=1;
error_counts=0;
menu=1;
//修改pwm输出频率,占空比
htim2.Init.Prescaler = 40-1;
htim2.Init.Period = 999;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,100);
duty=10;
freq=2000;
HAL_TIM_Base_Start_IT(&htim3);
Display_led();
}
//密码输入错误
else
{
is_correct=0;
menu=0;
error_counts++;
code_1=code_2=code_3=-1;
Display_led();
}
keys[3].key_flg=0;
}
}
main.c中涉及的函数以及定义的变量:
void sys_init()
{
//lcd初始化
LCD_Init();
LCD_Clear(Black);
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
//使能PWM输出
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
//打开定时器TIM2
HAL_TIM_Base_Start_IT(&htim4);
//打开串口接收
HAL_UART_Receive_IT(&huart1, &Rxdat, 1);
//初始状态的界面
Disp_Code_Enter();
//LED初始化
Contro_Led(1);
}
void sys_work()
{
//串口接收处理
GetData_uart();
Display_lcd(menu);
Key_Function();
}
/************************变量定义****************************/
//保存正确密码的变量
uint8_t code_one=1,code_two=2,code_thr=3;
//保存输入的密码
int8_t code_1=-1;
int8_t code_2=-1;
int8_t code_3=-1;
//保存频率,占空比的变量
uint16_t freq=1000;
uint8_t duty=50;
//保存当前显示的界面
//0--密码输入界面 1--参数显示界面
uint8_t menu=0;
//记录密码输入错误次数
uint8_t error_counts=0;
//记录此次输入密码是否正确
//0---输入错误 1--输入正确
uint8_t is_correct;
//定时器计数
uint16_t count=0;
//LED2的状态
unsigned char led2_sta;
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_TIM2_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
sys_init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
sys_work();
}
/* USER CODE END 3 */
}
总结
好啦,以上就是我对于实现第十三届省赛程序设计题的一些记录,希望可以帮助到看到的你们。
最后还是希望有不对的地方,可以告知一下我,十分感谢!