输入捕获,PWM输出,比较输出(一个定时器产生多路可调频率与占空比的PWM),RTC,ADC,UART,DMA,按键(长短按),LED,LCD,EEPROM,MCP4017。
串口功能:
使用DMA发送和接收,从串口接收到什么就发送什么,并在LCD显示,限制15个字节
ADC功能:
使用DMA采集R37和R38的电压
读取PB14电压
TIM功能:
TIM2:输入捕获,测量R40频率
TIM3:输入捕获,测量R39频率
TIM4:比较输出,一个定时器产生多路可调频率与占空比的PWM
TIM6:用于产生时间基准
TIM15:PWM输出,可调频率与占空比
(若无示波器,可用输入捕获测量PWM输出)
RTC功能:
RTC时间上电默认为23:59:50
闹钟时间默认为00:00:00
按键功能:
B1,切换模式,共有5个模式
B2,在设置频率模式下,改变PA2频率,在设置占空比模式下,改变PA2占空比
B3,在设置频率模式下,改变PA11频率,在设置占空比模式下,改变PA11占空比。在设置RTC下,设置闹钟时间。在TEST 2下,改变MCP4017阻值。
B4,在设置频率模式下,改变PA12频率,在设置占空比模式下,改变PA12占空比。在设置RTC下,设置RTC时间。在TEST 2下,改变MCP4017阻值。
每个按键具有长按功能,不限制模式皆可使用。
LED功能:
根据不同模式,点亮LD1-LD5。
每次闹钟时间到时,翻转LD8。
EEPROM功能:
识别设备第一次上电。
掉电保存开机次数。
MCP4017功能:
通过IIC读写MCP4017,改变其阻值,从而改变PB14的电压
按键模块
u8 KEY_SCAN(void)
{
u8 key=0,val;
static u8 com;
static u8 key_long_down=0; //长按标志位
static u16 key_num=0;
if(!TASK_TIMES.KEY_time)
{
TASK_TIMES.KEY_time=KEY_TIMEST;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET) val=1;
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET) val=2;
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET) val=3;
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET) val=4;
else val=0;
if(com==val)
{
if(key_long_down)
{
if(++key_num==5) //长按效果间隔50ms
{
key_num=0;
return val;
}
}
else if(++key_num==80) //长按800ms
{
key_num=0;key_long_down=1;
}
}
else
{
key_long_down=0;key_num=0;
}
key=val&(val^com);
com=val;
}
return key;
}
串口模块:
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==SET) //空闲中断
{
__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_IDLE); //清除空闲中断标志位
HAL_UART_DMAStop(&huart1); //停止串口1 DMA接收
UART1_RX_DATA_LEN=UART1_RX_LEN-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //获取本次接收长度
UART1_over=1; //接收完成标志位置1
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
u8 buf[20];
void UART_function(void)
{
u8 a;
if(UART1_over)
{
UART1_over=0; //接收完成标志位清零
CLEAR_BUF((u8 *)buf,15); //清空数组
if(UART1_RX_DATA_LEN>15) UART1_RX_DATA_LEN=15;
for(a=0;a<UART1_RX_DATA_LEN;a++)
{
buf[a]=UART1_RX_BUF[a];
}
HAL_UART_Transmit_DMA(&huart1,(u8 *)buf,UART1_RX_DATA_LEN); //使能串口1 DMA发送
if(!LCD_display)
{
sprintf((char *)LCD_Line_BUF[LCD_UART],"UART:%s",buf); //刷新LCD显示
LCD_state|=(0X01<<LCD_UART);
}
HAL_UART_Receive_DMA(&huart1,(u8 *)UART1_RX_BUF,UART1_RX_LEN); //使能串口1 DMA接收
}
}
MCP4017模块:
void MCP4017_function(void)
{
static u8 MCP4017_data_W_last=0;
if(MCP4017_data_W_last!=MCP4017_data_W)
{
MCP4017_data_W_last=MCP4017_data_W;
MCP4017_Write(MCP4017_data_W);
MCP4017_data_R=MCP4017_Read();
sprintf((char *)LCD_Line_BUF[LCD_4017_W]," MCP4017_W:%3d ",MCP4017_data_W);
sprintf((char *)LCD_Line_BUF[LCD_4017_R]," MCP4017_R:%3d ",MCP4017_data_R);
LCD_state|=(0X01<<LCD_4017_W); //刷新LCD
LCD_state|=(0X01<<LCD_4017_R); //刷新LCD
}
}
RTC模块:
void RTC_function(void)
{
static u8 Seconds_last;
if(!TASK_TIMES.RTC_time) //200ms读取一次RTC时间
{
TASK_TIMES.RTC_time=RTC_TIMEST;
HAL_RTC_GetTime(&hrtc,&RTC_Time,RTC_FORMAT_BIN); //获取时间
HAL_RTC_GetDate(&hrtc,&RTC_Date,RTC_FORMAT_BIN); //获取日期(hal库RTC的bug:如只获取时间不获取日期,时间不走时,需要同时获取时间和日期)
if(Seconds_last!=RTC_Time.Seconds) //RTC时间发生改变
{
Seconds_last=RTC_Time.Seconds;
if(!LCD_display)
{
sprintf((char *)LCD_Line_BUF[LCD_RTC],"RTC : %2d:%2d:%2d ",RTC_Time.Hours,RTC_Time.Minutes,RTC_Time.Seconds);
LCD_state|=(0x01<<LCD_RTC);
}
}
}
if(RTC_sAlarm) //闹钟
{
RTC_sAlarm=0; //闹钟标志位清零
LED_state^=(0x01<<7); //每次闹钟时间到,翻转LD1
}
}
LCD模块:
void LCD_function(void)
{
u8 a;
for(a=0;a<10;a++) //扫描LCD的10行状态
{
if(LCD_state&(0x01<<a)) //检测到该行状态发生改变
{
LCD_state&=(~(1<<a)); //清除该行状态
LCD_DisplayStringLine(a*24,LCD_Line_BUF[a]); //刷新该行显示
}
}
}
效果展示:
完成程序下载:
链接:https://pan.baidu.com/s/1LMECSy3GuABduu42YUJdSQ
提取码:qy2o