上一次做了第十一届的国赛赛题,感觉很容易。然后这两天做了第十届的赛题,感觉第十届的赛题是十一届难度的两倍。这一届的赛题考察的内容特别多,并且逻辑方面相比十一届也是难度大一些的,所以正式比赛的时候,如果不是特别熟悉,还有可能不能把全部的功能都实现。这一届考察的内容大致如下:
LED |
---|
LCD,LCD的高亮显示 |
独立按键,长按 |
双通道ADC转换 |
定时器的输入捕获,检测占空比 |
EEPROM数据的读写,使用EEPEOM存放16位数据 |
DS18B20,精确到两位小数 |
USAR串口的收发 |
数码管显示 |
这一届的题目还是挺有意义的,难度有一丢丢大,拿来赛前练手挺好的。
ADC2的配置
主要注意一下,我们用到了ADC2的两个通道,所以这里我们使用了DMA,每个通道转换完成的数据就会由DMA直接将对应的数据存放到相应的存储器中,所以我们后面只需要读取对应的存储器的值即可。如果不使用DMA也是可以的, 要麻烦一点,网上有很多资料,这里就不多说。
ADC配置需要注意的是,要先添加DMA,然后才能在ADC的参数设置中使能ADC DMA转换,除此之外还要使能扫描转换,以及连续转换模式,否则只能自动转换一次ADC的数据,后面的每一次都要重新使能。
定时器输入捕获
其中81 - 1 分频是将定时器的时钟配置为1MHz。因为在系统时钟为80MHz。重转载计数器一定要设置为最大,对于16位的寄存器最大值也就是65535。
#define SEG_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET)
#define SEG_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET)
#define RCK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET)
#define RCK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET)
#define SCK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET)
#define SCK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET)
uint
8_t seg_buf[] = {
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x39,0x77,0x00};
void seg_set(uint8_t seg1,uint8_t seg2,uint8_t seg3)
{
uint32_t seg = (seg_buf[seg3] << 16) | (seg_buf[seg2] << 8) | seg_buf[seg1];
uint8_t i;
for(i = 0; i < 24; i++)
{
if(seg & 0x800000)
SEG_H;
else
SEG_L;
seg <<= 1;
SCK_H;
SCK_L;
}
RCK_H;
RCK_L;
}
void highlight(u8 Line, u8 *ptr)
{
u32 i = 0;
u16 refcolumn = 319;//319;
while ((*ptr != 0) && (i < 20)) // 20
{
if(((Line == Line3 && select == 0) || (Line == Line4 && select == 1)) && (i > 0 && i < 18))
LCD_SetBackColor(Yellow);
else
LCD_SetBackColor(Black);
LCD_DisplayChar(Line, refcolumn, *ptr);
refcolumn -= 16;
ptr++;
i++;
}
}
if(key_state == B3 && interface == PARA && select == 0 && ++key_cnt == 90)
{
key_cnt = 80;
if(temp_upper_temp < 40)
temp_upper_temp++;
}
if(key_state == B4 && interface == PARA && select == 0 && ++key_cnt == 90)
{
key_cnt = 80;
if(temp_upper_temp > 20)
temp_upper_temp--;
}
if(key_state == 0)
{
key_cnt = 0;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim -> Instance == TIM3)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
if(CaptureNumber == 0)
{
/* Get the Input Capture value */
IC3ReadValue1 = TIM3->CCR2;
CaptureNumber = 1;
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
}
else if(CaptureNumber == 1)
{
/* Get the Input Capture value */
IC3ReadValue2 = TIM3->CCR2;
CaptureNumber = 2;
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
if (IC3ReadValue2 > IC3ReadValue1)
{
Capture_High = (IC3ReadValue2 - IC3ReadValue1);
}
else
{
Capture_High = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);
}
IC3ReadValue1 = IC3ReadValue2;
}
else if(CaptureNumber == 2)
{
/* Get the Input Capture value */
IC3ReadValue2 = TIM3->CCR2;
CaptureNumber = 0;
if (IC3ReadValue2 > IC3ReadValue1)
{
Capture_Low = (IC3ReadValue2 - IC3ReadValue1);
}
else
{
Capture_Low = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);
}
/* Frequency computation */
TIM3Freq = (uint32_t) 1000000 / (Capture_Low + Capture_High);
TIM3Duty = Capture_High * 1.0 / (Capture_Low + Capture_High);
pwm2 = TIM3Duty;
}
}
}
}
数据的处理代码如下:
void usart_proc(void)
{
if(channel_x == A01 && a01 > pwm2 * 3.3 && usart_flag)
{
usart_flag = 0;
printf("$%.2f\r\n",temperature);
}
else if(channel_x == A02 && a02 > pwm2 * 3.3 && usart_flag)
{
usart_flag = 0;
printf("$%.2f\r\n",temperature);
}
if((channel_x == A01 && a01 <= pwm2 * 3.3) || (channel_x == A02 && a02 <= pwm2 * 3.3))
{
usart_flag = 0;
usart_tick = 0;
}
if(UART1_IDLE_Flag)
{
UART1_IDLE_Flag = 0;
// memset(lcd_str,0,sizeof(lcd_str));
// snprintf((char*)lcd_str,20,"%s",RxBuffer);
// LCD_DisplayStringLine(Line9, lcd_str);
if(strcmp((const char *)RxBuffer,"ST\r\n") == 0)
{
printf("$%.2f\r\n",temperature);
}
else if(strcmp((const char *)RxBuffer,"PARA\r\n") == 0)
{
printf("#%d,AO%d\r\n",temp_upper,channel_x + 1);
}
memset(RxBuffer,0,sizeof(RxBuffer));
RxCounter = 0;
}
}
代码使用说明,一定要看
完整代码下载点我