目录
题目要求:
所用到的引脚和外设:
软件设计:
主函数编写:
CubeMX配置:
PWM:编辑
USART:串口
PWM使用注意事项:
USART1:串口使用注意事项:
对while循环的两个函数进行分析:
KEY_scanf();函数:
Lcd_Dis();函数:
效果显示:
LCD:
串口通信:USART1:PA9、PA10
按键:PB0、PB1、PB2、PA0
PWM波:PA1
LED:PC8~15、PD2
对LCD和按键经行定时扫描,一系类的函数都在定时扫描中进行。我的编程习惯呐,喜欢先将分模块写出来,然后根据逻辑将模块整合。
#include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h" #include "lcd.h" //中断暂存变量 unsigned char rxData; uint8_t Default_Password[3]={1,2,3};//密码存储地 uint8_t affim_Key4=0;//统计按键次数的相关变量 uint8_t Led2_Fre=0; _Bool LED2_Swap=0; void SystemClock_Config(void); int main(void) { HAL_Init(); SystemClock_Config(); LCD_Init(); MX_GPIO_Init(); MX_TIM2_Init(); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); MX_USART1_UART_Init(); HAL_UART_Receive_IT(&huart1,&rxData,1); mimajiemian(); Led_Control(0x00); while (1) { KEY_scanf(); Lcd_Dis(); } }
主函数当中就两个函数一个是按键一个是lcd显示,这套题需要注意的外设有PWM和串口。
USART1引脚:PA9、PA10
其余配置请参考我的下边这篇文章:
http://t.csdn.cn/p6tPThttp://t.csdn.cn/p6tPT
注意:使用PWM的时候先对定时器进行初始化,
然后开启定时器PWM:HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);。
修改占空比使用:__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,DU);
占空比:Du/Fre ;
修改频率使用:
htim3.Init.Period = Fre; HAL_TIM_Base_Init(&htim3);
注意:使用串口的时候先进行串口等配置的初始化,
然后如果要中断接收数据的话就需要:HAL_UART_Receive_IT(&huart1,&rxData,1);
打开中断接收,位置在初始化的下一句就行。
然后是中断回调函数的编写:将HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)在usart.c文件中重新调用一下,然后在该函数里边进行数据的接收。
先转跳近函数的主体:
void KEY_scanf(void)
{
if(uwTick-uwTick_KEY_Last<50) return ;
uwTick_KEY_Last=uwTick;
Key_N_Val=Key_Val();
Key_Down=Key_N_Val & (Key_N_Val^Key_Last_Val);
Key_Up=~Key_N_Val & (Key_N_Val^Key_Last_Val);
Key_Last_Val=Key_N_Val;
Key_control();
//密码确认和led2闪烁
mimaquer();
}
这部分代码是对按键进行定时扫描,然后进行一些和按键控制有关的函数里边,
Key_control();//该函数控制着按键1、2、3的加减,控制按键4的确认。
mimaquer();//该函数里边包含密码确认和led2的闪烁
void mimaquer(void)
{
if(B4==1)//按键4的确认
{
B4=0;
affim_Key4+=1;//输入密码累加计数
if(B1==Default_Password[0]&&
B2==Default_Password[1]&&
B3==Default_Password[2])//密码确认
{
model=1;//显示模式
Fre_2000hz_Control();//2000Hz控制
affim_Key4=0; //如果密码正确输入次数累加清零
}
B1=10; //B1显示 @
B2=10; //B2显示 @
B3=10; //B3显示 @
}
if(affim_Key4>=3) //如果输入次数大于等于3
{
Led2_Fre+=1;//用于计时累加的
if(Led2_Fre%2==0)//闪烁
{
LED2_Swap=(_Bool)(1-LED2_Swap);
if(LED2_Swap==1)
{
Led_Control(0x02);
}
if(LED2_Swap==0)
{
Led_Control(0x00);
}
}
if(Led2_Fre>=90)//5s过后
{
Led2_Fre=0;
affim_Key4=0;
Led_Control(0x00);
}
}
}
void Lcd_Dis(void)
{
if(uwTick-uwTick_LCD_last<200) return ;
uwTick_LCD_last=uwTick;
if(model==0)//密码输入界面
{
mimajiemian();//密码输入界面显示
}
else//输出界面
{
Rbt+=1;
if(Rbt<25)
{
Out_interface();//输出界面显示
Led_Control(0x01);//led控制
}
else
{
Rbt=0;
model=0;
Fre_1000hz_Control();//返回密码输入界面的频率
Led_Control(0x00);
}
}
密码输入是从@开始到0~9的循环。我在这里规定了一个数组在第十位显示@,而按键按下的时候按键加一在数组里遍历。然后当遍历到第十位的时候等于0从头开始遍历。
char Cipher[11]={'0','1','2','3','4','5','6','7','8','9','@'};
void mimajiemian(void)
{
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
sprintf((char *)Lcd_dis," ");
LCD_DisplayStringLine(Line0,Lcd_dis);
sprintf((char *)Lcd_dis," PSD ");
LCD_DisplayStringLine(Line1,Lcd_dis);
sprintf((char *)Lcd_dis," ");
LCD_DisplayStringLine(Line2,Lcd_dis);
sprintf((char *)Lcd_dis," B1:%c ",Cipher[B1]);//注意
LCD_DisplayStringLine(Line3,Lcd_dis);
sprintf((char *)Lcd_dis," B2:%c ", Cipher[B2]);
LCD_DisplayStringLine(Line4,Lcd_dis);
sprintf((char *)Lcd_dis," B3:%c ",Cipher[B3]);
LCD_DisplayStringLine(Line5,Lcd_dis);
sprintf((char *)Lcd_dis," ");
LCD_DisplayStringLine(Line6,Lcd_dis);
LCD_DisplayStringLine(Line7,Lcd_dis);
LCD_DisplayStringLine(Line8,Lcd_dis);
LCD_DisplayStringLine(Line9,Lcd_dis);
}
视频例程