笔者参加了今年的第十三届蓝桥杯国赛,取得了国二的成绩,虽然没能拿到国一但依然很开心了。在这里给大家分享我的代码和一些做题思路,希望能凭一己之力提高蓝桥杯嵌入式的水平哈哈哈哈。
一、cubemx配置
①整体配置
②UART
③双通道ADC(DMA)
转化后的结果用字也就是32bit
把连续转换和DMA打开
注意转换顺序也就是这里的排名rank
采样时间不能默认值,要设置为24.5 cycles,不然两个口会相互干扰
④输入捕获和输出比较
分频倍频我认为最好的做法
让预分频系数相等
倍频 比较输出的周期=输入捕获的计时器数/2/倍频数
分频 比较输出的周期=输入捕获的计时器数/2*倍频数
A、输入捕获为从模式的复位模式,复位来源是通道二
B、比较输出的模式是翻转模式
⑤NVIC中断级分组
⑥时钟配置
二、代码
代码我几乎全部写在main.c里面
#include "stdio.h"
#include "string.h"
#include "lcd.h"
#include "i2c.h"
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
void SystemClock_Config(void);
//LED
uint8_t ucled=0x09,ld3_state;
__IO uint32_t LED_tick;
void LED_disp(uint8_t led);
//LCD
uint8_t lstring[25],LCD_state,PARA_cstate,IN_state;
void LCD_pro();
//KEY
uint8_t nkey,okey,ukey,dkey;
__IO uint32_t KEY_tick,KEY_longtick;
uint8_t KEY_scan();
void KEY_pro();
//ADC
uint32_t ADC_val[40],ADC[2];
float V[2];
uint8_t ADC_state;
void ADC_pro();
//UART
uint8_t RX_buf,RX_BUF[128],RX_CNT;
__IO uint32_t UART_tick;
void UART_pro();
//IC
uint32_t IC_circle;
//
uint32_t OC_circle;
//EEPROM
uint8_t eeprom[2];
//USER
uint8_t PARA[2]={1,1},mode;
float PA4_data[100],PA5_data[100],A[2],T[2],H[2];
uint8_t N[2],loc[2];
int fputc(int c,FILE* stream)
{
HAL_UART_Transmit(&huart1,(uint8_t*)&c,1,1000);
return c;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC2_Init();
MX_TIM2_Init();
MX_TIM17_Init();
MX_USART1_UART_Init();
LCD_Init();
I2CInit();
LED_disp(ucled);
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
HAL_TIM_OC_Start_IT(&htim17,TIM_CHANNEL_1);
HAL_ADC_Start_DMA(&hadc2,ADC_val,40);
HAL_UART_Receive_IT(&huart1,&RX_buf,1);
I2CRead(eeprom,0,2);
if(eeprom[0]>=1&&eeprom[0]<=4&&eeprom[1]>=1&&eeprom[1]<=4)
{
PARA[1]=eeprom[0];
PARA[0]=eeprom[1];
}
// if(eeprom[2]==0x65&&eeprom[3]==0x99&&eeprom[4]==0xfa)//第一次上电检测
// {
// memcpy(PARA,eeprom,2);
// }
// else
// {
// memcpy(eeprom,PARA,2);
// eeprom[2]=0x65;eeprom[3]=0x99;eeprom[4]=0xfa;
// I2CWrite(eeprom,0,5);
// }
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
// LCD_DisplayStringLine(Line1, (uint8_t *)" DATA ");//LCD的显示调试
// LCD_DisplayStringLine(Line3, (uint8_t *)" PA4=3.02 ");
// LCD_DisplayStringLine(Line4, (uint8_t *)" PA5=3.02 ");
// LCD_DisplayStringLine(Line5, (uint8_t *)" PA1:2046 ");
//
// LCD_DisplayStringLine(Line1, (uint8_t *)" PARA ");
// LCD_DisplayStringLine(Line3, (uint8_t *)" X=1 ");
// LCD_DisplayStringLine(Line4, (uint8_t *)" Y=1 ");
//
// LCD_DisplayStringLine(Line1, (uint8_t *)" REC-PA4 ");
// LCD_DisplayStringLine(Line3, (uint8_t *)" N=23 ");
// LCD_DisplayStringLine(Line4, (uint8_t *)" A=3.02 ");
// LCD_DisplayStringLine(Line5, (uint8_t *)" T=3.02 ");
// LCD_DisplayStringLine(Line6, (uint8_t *)" H=1.52 ");
while (1)
{
KEY_pro();
LCD_pro();
ADC_pro();
UART_pro();
}
}
void LED_disp(uint8_t led)
{
GPIOC->ODR=~led<<8;
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
uint8_t KEY_scan()
{
if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)) return 1;
if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)) return 2;
if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)) return 3;
if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)) return 4;
return 0;
}
void KEY_pro()
{
if(uwTick-KEY_tick<5) return;
KEY_tick=uwTick;
nkey=KEY_scan();
dkey=nkey&(nkey^okey);
ukey=~nkey&(nkey^okey);
if(dkey)
{
KEY_longtick=uwTick;
}
if(LCD_state==2)
{
if(uwTick-KEY_longtick<1000)
{
if(ukey==4)
{
IN_state=!IN_state;
}
}
else
{
if(ukey==4)
{
if(IN_state)
{
memset(PA5_data,0,sizeof(PA5_data));
N[1]=0;
A[1]=0;
T[1]=0;
H[1]=0;
loc[1]=0;
}
else
{
memset(PA4_data,0,sizeof(PA4_data));
N[0]=0;
A[0]=0;
T[0]=0;
H[0]=0;
loc[0]=0;
}
}
}
}
if(okey!=nkey)
{
switch(nkey)
{
case 1:
{
LCD_Clear(Black);
LCD_state=(LCD_state+1)%3;
if(LCD_state==2){IN_state=0;}
break;
}
case 2:
{
if(LCD_state==1)
{
PARA[0]=(PARA[0])%4+1;
I2CWrite(PARA,1,1);
}
break;
}
case 3:
{
if(LCD_state==1)
{
PARA[1]=PARA[1]%4+1;
I2CWrite(PARA+1,0,1);
if(V[0]>V[1]*PARA[1]&&ld3_state!=1)
{
ld3_state=1;
LED_tick=uwTick;
}
if(V[0]<=V[1]*PARA[1]&&ld3_state!=0)
{
ld3_state=0;
LED_disp(ucled&=~0x04);
}
}
break;
}
case 4:
{
if(LCD_state!=2)
{
if(LCD_state==0)
{
ADC_state=1;
}
else
{
LED_disp(ucled^=0x03);
mode=!mode;
}
}
break;
}
}
}
okey=nkey;
}
void LCD_pro()
{
switch(LCD_state)
{
case 0:
{
LCD_DisplayStringLine(Line1, (uint8_t *)" DATA ");
sprintf((char*)lstring," PA4=%.2f ",V[0]);
LCD_DisplayStringLine(Line3,lstring);
sprintf((char*)lstring," PA5=%.2f ",V[1]);
LCD_DisplayStringLine(Line4,lstring);
sprintf((char*)lstring," PA1:%d ",(uint32_t)(1000000.0/IC_circle+0.5));
LCD_DisplayStringLine(Line5,lstring);
break;
}
case 1:
{
LCD_DisplayStringLine(Line1, (uint8_t *)" PARA ");
sprintf((char*)lstring," X=%d ",PARA[0]);
LCD_DisplayStringLine(Line3,lstring);
sprintf((char*)lstring," Y=%d ",PARA[1]);
LCD_DisplayStringLine(Line4,lstring);
break;
}
case 2:
{
sprintf((char*)lstring," REC-PA%d ",IN_state+4);
LCD_DisplayStringLine(Line1,lstring);
sprintf((char*)lstring," N=%d ",N[IN_state]);
LCD_DisplayStringLine(Line3,lstring);
sprintf((char*)lstring," A=%.2f ",A[IN_state]);
LCD_DisplayStringLine(Line4,lstring);
sprintf((char*)lstring," T=%.2f ",T[IN_state]);
LCD_DisplayStringLine(Line5,lstring);
sprintf((char*)lstring," H=%.2f ",H[IN_state]);
LCD_DisplayStringLine(Line6,lstring);
break;
}
}
}
void ADC_pro()
{
if(ADC_state)
{
ADC_state=0;
ADC[0]=0;
ADC[1]=0;
for(int i=0;i<20;i++)
{
ADC[0]+=ADC_val[2*i];
ADC[1]+=ADC_val[2*i+1];
}
ADC[0]=(uint32_t)(ADC[0]/20.0+0.5);
ADC[1]=(uint32_t)(ADC[1]/20.0+0.5);
V[0]=ADC[0]*3.3/4096;
V[1]=ADC[1]*3.3/4096;
PA4_data[loc[0]]=V[0];
PA5_data[loc[1]]=V[1];
loc[0]=(loc[0]+1)%100;
loc[1]=(loc[1]+1)%100;
if(V[0]>V[1]*PARA[1]&&ld3_state!=1)
{
ld3_state=1;
LED_tick=uwTick;
}
if(V[0]<=V[1]*PARA[1]&&ld3_state!=0)
{
ld3_state=0;
LED_disp(ucled&=~0x04);
}
if(N[0]!=100)
{
N[0]++;
}
if(N[1]!=100)
{
N[1]++;
}
A[0]=T[0]=PA4_data[0];
A[1]=T[1]=PA5_data[0];
H[0]=0;
H[1]=0;
for(int i=0;i<N[0];i++)
{
if(A[0]<PA4_data[i])
{
A[0]=PA4_data[i];
}
if(T[0]>PA4_data[i])
{
T[0]=PA4_data[i];
}
H[0]+=PA4_data[i];
}
for(int i=0;i<N[1];i++)
{
if(A[1]<PA5_data[i])
{
A[1]=PA5_data[i];
}
if(T[1]>PA5_data[i])
{
T[1]=PA5_data[i];
}
H[1]+=PA5_data[i];
}
H[0]=H[0]/N[0];
H[1]=H[1]/N[1];
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
IC_circle=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
uint16_t cnt;
cnt=HAL_TIM_ReadCapturedValue(&htim17,TIM_CHANNEL_1);
if(mode)
{
__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,cnt+IC_circle/2*PARA[0]);
}
else
{
__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,cnt+IC_circle/2/PARA[0]);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
RX_BUF[RX_CNT++]=RX_buf;
if(RX_CNT>=127)
{
RX_CNT=0;
HAL_UART_Transmit(&huart1,(uint8_t*)"error",5,1000);
}
else
{
UART_tick=uwTick;
}
HAL_UART_Receive_IT(&huart1,&RX_buf,1);
}
void UART_pro()
{
if(RX_CNT&&uwTick-UART_tick>3)
{
if(memcmp(RX_BUF,"X",1)==0&&RX_CNT==1)
{
printf("X:%d\r\n",PARA[0]);
}
else if(memcmp(RX_BUF,"Y",1)==0&&RX_CNT==1)
{
printf("Y:%d\r\n",PARA[1]);
}
else if(memcmp(RX_BUF,"PA1",3)==0&&RX_CNT==3)
{
printf("PA1:%d\r\n",(uint32_t)(1000000.0/IC_circle+0.5));
}
else if(memcmp(RX_BUF,"PA4",3)==0&&RX_CNT==3)
{
printf("PA4:%.2f\r\n",V[0]);
}
else if(memcmp(RX_BUF,"PA5",3)==0&&RX_CNT==3)
{
printf("PA5:%.2f\r\n",V[1]);
}
else if(memcmp(RX_BUF,"#",1)==0&&RX_CNT==1)
{
LCD_mode=!LCD_mode;
LCD_Clear(Black);
LED_disp(ucled^=0x08);
}
else printf("error!\r\n");
RX_CNT=0;
}
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
HAL_IncTick();
if(ld3_state)
{
if(uwTick-LED_tick==100)
{
LED_tick=uwTick;
LED_disp(ucled^=0x04);
}
}
}
难点LCD翻转
我采用的方法是改两个函数,使用了extern LCD_mode
但最好的方法应该是写寄存器使LCD的扫描方向改变
最后把我的分数估一下,以后让你们有一个参考
我是客观题错五个左右+eeprom存错位置+LD3一个小问题+每次切换到ADC数据页面时没有默认PA4+LCD切换翻转了但是字母左右是反的
最终估分85分左右