目录
一、题目分析
题目总体来看,其实并不难。用到了模块也不复杂,主要用到了led、按键、定时器、串口模块。对于本题的作者源码在文章的末尾,下面是我对题目的一些理解,不对之处还望指正。
在本道题中,PA1脚输出1kHZ的方波或者2kHZ占空比为10%的pwm波是本道题比较难的点,我使用的方法是PA1所在引脚定时器2的输出比较模式,这样就可以实现引脚输出不同的频率不同占空比的pwm波了。
还有就是@的显示 其实这个用字符打印会比较简单。使用sprintf();%c打印出来,@对应的ASCLL码值是64。
具体实现看下面代码或者在文章末尾下载源码。
二、代码分析
界面切换
void LCD_Display(uint8_t LCDShow_Flag,int8_t BS1,int8_t BS2,int8_t BS3,uint16_t Feruq,uint8_t Duty)
{
uint8_t string[21];
//数据界面
if(LCDShow_Flag==0)
{
LCD_DisplayStringLine(Line1,(unsigned char *)" PSD");
//BS1
sprintf((char*)string,"%s%c "," B1:", BS1);
LCD_DisplayStringLine(Line3,string);
//BS2
sprintf((char*)string,"%s%c "," B2:", BS2);
LCD_DisplayStringLine(Line4,string);
//BS3
sprintf((char*)string,"%s%c "," B3:", BS3);
LCD_DisplayStringLine(Line5,string);
}
//参数界面
else
{
LCD_DisplayStringLine(Line1,(unsigned char *)" STA");
//清屏
LCD_ClearLine(Line5);
sprintf((char*)string,"%s%dHZ "," F:",Feruq);
LCD_DisplayStringLine(Line3,string);
sprintf((char*)string,"%s%d%% "," D:",Duty);
LCD_DisplayStringLine(Line4,string);
}
}
pwm输出代码如下。
#include "pwm.h"
//pwm频率
uint16_t CCR2_Val1 = 1000; //80000000/80/1000
uint16_t CCR2_Val2 = 500; //80000000/80/2000
uint8_t PA1_Flag=0;
extern uint16_t Feruq;
extern uint8_t Duty;
extern uint8_t LCDShow_Flag;
extern int8_t BS1,BS2,BS3;
//定时器输出比较回调函数
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
uint16_t capture=0;
uint16_t temp=0;
static uint16_t num=0;
if(htim->Instance == TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
//获取定时器的计数值
capture = __HAL_TIM_GetCounter(htim);
//1K
if(LCDShow_Flag == 0)
{
Feruq=1000;
Duty=50;
if(PA1_Flag==0)
{
PA1_Flag=1;
temp = capture+CCR2_Val1/2;
temp %= 65535;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
}
else
{
PA1_Flag=0;
temp = capture+CCR2_Val1/2;
temp %= 65535;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
}
}
//2K
else
{
Feruq=2000;
Duty=10;
if(PA1_Flag==0)
{
PA1_Flag=1;
num++;
temp = capture+CCR2_Val2*0.1;
temp %= 65535;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
}
else
{
PA1_Flag=0;
temp = capture+CCR2_Val2*0.9;
temp %= 65535;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
}
}
if(num>=10000)
{
num=0;
LCDShow_Flag=0;
BS1=64;
BS2=64;
BS3=64;
}
}
}
}
串口合法性判断
//串口数据合法性判断
void USART_Analysis(uint8_t* ptr,uint16_t n)
{
if(n == 6)
{
if(ptr[3]=='-')
{
if((ptr[0]==PSD_Num[0]) && (ptr[1]==PSD_Num[1]) && (ptr[2]==PSD_Num[2]))
{
if(((ptr[4]>='0')&&(ptr[4]<='9')) && ((ptr[5]>='0')&&(ptr[5]<='9')) && ((ptr[6]>='0')&&(ptr[6]<='9')))
{
PSD_Num[0]=ptr[4];
PSD_Num[1]=ptr[5];
PSD_Num[2]=ptr[6];
HAL_UART_Transmit(&huart1,PSD_Num,3,0xffff);
}
}
}
}
}
主函数
while (1)
{
//key
KeyValue=KeyScan();
switch(KeyValue)
{
case 1:
BS1 = Key_PSDNumChang(BS1,LCDShow_Flag);
break;
case 2:
BS2 = Key_PSDNumChang(BS2,LCDShow_Flag);
break;
case 3:
BS3 = Key_PSDNumChang(BS3,LCDShow_Flag);
break;
case 4:
LCDShow_Flag=PSD_PanDuan(&BS1,&BS2,&BS3,PSD_Num);
break;
}
//串口
if(USART1_Rx_STA&0x8000)
{
USART_Analysis(USART1_Rx_BUF,(USART1_Rx_STA&0x7fff)-1);
USART1_Rx_STA=0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//LCD显示
LCD_Display(LCDShow_Flag,BS1,BS2,BS3,Feruq,Duty);
//led显示
LedDisplay(LedShow_Flag,LedTog_Flag);
}
/* USER CODE END 3 */
}
定时器输出比较模式,在比较寄存器值和定时器的计数值相等的时候出发中断,这个时候我们可以在中断回调函数中修改比较寄存器的值,就可以实现PA1引脚输出1KHZ的方波或者2KHZ占空比为10%的PWM波。
在代码中有PA1_Flag,这个变量是来标记输出PWM波的高低电平,PA1_Flag=0为高电平,否则为低电平。
在Cube中配置要把该引脚通道配置成翻转模式。
大致就说到这里,代码工程在下面,大家可以自取。只供学习使用,不对之处还望指正。欢迎大家留言。
源代码链接
链接:https://pan.baidu.com/s/1DCjDq41gdhQzoMUOZ7qqCg
提取码:mwl7