前些天参加了蓝桥杯嵌入式比赛省赛,没太在意这个竞赛,备考三天,遗憾省二,有点心疼自己的报名费。谨作记录,方便明年去刷分。
今年嵌入式可以使用新版开发板,但据我观察考点里大家都用的是旧版的板子(我去的比较晚,快九点才到考场)。考试时考点提供了CubeMx,我也就使用Cube配置Hal库完成了比赛。
事实上由于我已经很长时间没怎么使用过Stm32,标准库已经忘得差不多了,是考前三天看了看Hal库相关知识,就直接莽了,至于客观题,我并没有花什么时间去准备,因为感觉这个东西考的知识面还是比较广,认真准备的话还是得花个好几天,但我那些天实在是太忙啦,加上不想多为这个比赛费神,就没去准备客观题,最后也没去对答案,但有时间的话去准备准备客观题的话,后面还是很有希望拿省一的,毕竟排在我前面的那个人刚好就是省一,,鬼鬼,这么一说我运气好差哦。
比较难受的是,考点没有提供旧版F1平台的HAL库例程,只提供了标准库例程,然后就只能我自己建立工程,过程中由于没有LCD的HAL库例程,浪费了二三十分钟时间(考试中我尝试将新版平台的LCD例程移植到旧版,未能成功,后发现是两块板子连接LCD的引脚不同,遂放弃,改为将F1的LCD标准库代码修改成HAL库代码,过程中花费了许多时间,导致后面写逻辑代码的时间不够了)。
五个小时的考试时间说短不短,但我在开考的时候浪费了许多时间在硬件配置调试上面,后面中午又饿了在吃自己带的午餐,导致最后在进行串口数据调试之后,就没有时间再去完成车辆数目的统计与调试了。下次,emmm,下次未必会再报这个比赛,报名费也太贵了,学校又不报销!!!!!
/************************************************************************************************************************/
hal库工程建立:
1:SYS里面配置DEBUG JTAG(4 wire)
2: RCC HSE配为Crystal, 系统时钟记住配置成72M
3: LCD所有的Pin都是GPIO OutPut
4: PB4 配为 OutPut HIGH,关闭蜂鸣器
5:error: L6236E: No section matches selector - no section to be FIRST/LAST. 往工程里添加启动文件
6:#define COL(X) (319-(X)*16+16) //用于LCD列显示,LCD_DisplayChar(Line9,COL(19),'0');
7: 24C02使用应当调用 I2CInit();
8: 手撸驱动代码
// 24C02读取一字节
unsigned char x24c02_read(unsigned char address)
{
unsigned char i;
I2CStart();
I2CSendByte(0xa0);I2CWaitAck();
I2CSendByte(address);I2CWaitAck();
I2CStart();
I2CSendByte(0xa1); I2CWaitAck();
i=I2CReceiveByte(); I2CWaitAck();
I2CStop();
delay1(500);
return(i);
}
// 24C02写入一字节
void x24c02_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0xa0); I2CWaitAck();
I2CSendByte(address); I2CWaitAck();
I2CSendByte(info); I2CWaitAck();
I2CStop();
delay1(65000);
}
9:ADC DMA转换 Continuous Conversion Mode: Enable DMA Request Settings: Circular Sampling time: 41.5 Cycles
转换数据一定要用数组存储
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adc_data,1);//开启ADC DMA转换
10: 消抖程序
//思路参考自正点原子的例程
void key_sacn(unsigned char mode)
{
static unsigned char key_up=1;//按键松开标志位,默认松开
if(mode) key_up=1;//连按功能
if((KEY1==0||KEY2==0||KEY3==0||KEY4==0)&&key_up==1) //按下按键且之前是松开的进入逻辑
{
HAL_Delay(10);
key_up=0; //按键已经按下,标志位复位,这一步很重要
if(KEY1==0)
{
key_now++;
return; //return is perfect!
}
else if(KEY2==0)
{
key_now++;
return;
}
else if(KEY3==0)
{
key_now++;
return;
}
else if(KEY4==0)
{
key_now++;
return;
}
}
else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1&&key_up==0)
{
key_up=1; // 判断松开和按下需要平级
// key_now = 0;
return;
}
}
11: 定时器中断:
TIM2-5为通用定时器
Clock Source: Internal, Clock Prtscaler: 7199 72M/(7199+1)=10000HZ
Counter Mode: Up
Counter Period: 4999 (4199+1)/10000 = 0.5S = 500MS
CKD : No Division
auto-reload-preload : Enable
在Cube中使能定时器全局中断
HAL_TIM_PeriodElapsedCallback() //中断回调函数
HAL_TIM_Base_Start_IT(&htim2); //开启定时器中断
12:串口中断接收和发送
HAL_UART_RxCpltCallback() //接收中断回调,在接收完设定数目数据后回调,在里面设一个接收完成标志位
HAL_UART_Receive_IT(&huart2,rx_husart2.data, 10); //设置接收中断,每接收完设定数目后,需重新执行该函数,在主循环中据接收完成标志位重设该函数
HAL_UART_Transmit_IT(&huart2,rx_husart2.data, 10); //串口中断发送函数
13:PWM Generate: Internal Clock ,71(主频-1),499 72M/72/500=2KHZ,频率2KHZ,可设占空比0-499
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,200);
14:输入捕获 Input Capture direct mode , Clock Prtscaler: 71 Counter Period: 0xffff auto-reload-preload : Enable
HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_2); //IC; InputCapture
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim==&htim4)
{
time_pre=time_now;
time_now=HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_2);
time_us+=(time_now-time_pre);
count++;
if(count%2)
__HAL_TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING);
else
__HAL_TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);
}
}
15:
/************************************************************************************************************************/