新手小白17届蓝桥杯单片机赛道学习备赛总结(基于西风的模板)

张开发
2026/4/13 9:16:49 15 分钟阅读

分享文章

新手小白17届蓝桥杯单片机赛道学习备赛总结(基于西风的模板)
一、数码管中的特殊显示1.小数的显示需要①乘以一定倍数②强制类型转换。易错点1.1 如果乘以一定倍数后大于255应该强制转换成unsigned int而不是unsigned char2.1 “%” 运算的对象不能是浮点数因此需要先转换成整形再进行类型转换float para 35.7; Seg_Buf[0] (unsigned char)para/10; //取十位 Seg_Buf[1] (unsigned char)para%10; //取个位 Seg_Buf[2] (unsigned int)(para*10)%10; //取十分位 //取十分位时要注意运算顺序是扩大10倍后先转换类型再取余 //取余运算的对象只能是整形 Seg_Point[1] 1; //显示小数点2.高位熄灭使用三目运算符:(判断表达式)?(表达式为true执行此括号中的语句并返回值)(表达式为false执行此括号中的语句并返回值)unsigned char para 120; Seg_Buf[0] (para 100)?(para/100%10):(10); //取百位 Seg_Buf[1] (para 10)?(para/10%10):(10); //取十位 Seg_Buf[2] para%10; //取个位常见问题2.1 数值为100时显示为00误把判断表达式中的符号“”,写成了“”2.2 数值为0时3位数码管全部熄灭取个位时注意是不用使用三目运算符的3.显示负号难点负数的位数不定可能是两位数可能是一位数//验证得int para 0,para -1,para -15时下列代码均可正常显示其数值 Seg_Buf[5] abs(para)/100%10; //取百位 Seg_Buf[6] abs(para)/10%10; //取十位 Seg_Buf[7] abs(para)%10; //取个位 //注意当para为float类型时要用的应该是“fabs()”; //当para为long int类型时要用的应该是“labs()”; //这些函数在math.h中 i 5; while(Seg_Buf[i] 0) { if(i 7) return; } if(Seg_Buf[i] ! 0) Seg_Buf[i-1] 11; //11是负号“-”对应的段码二、串口无法发送数据1.主函数中 忘记调用串口初始化函数2.串口初始化中忘记开中断void Uart1_Init(void) //9600bps12.000MHz { SCON 0x50; //8位数据,可变波特率 AUXR | 0x01; //串口1选择定时器2为波特率发生器 AUXR 0xFB; //定时器时钟12T模式 T2L 0xE6; //设置定时初始值 T2H 0xFF; //设置定时初始值 AUXR | 0x10; //定时器2开始计时 ES 1; //使能串口1中断 EA 1; //使能总中断 } //以上代码可以在STC_ISP“串口波特率计算器”中生成 //但是勾选“使能串口中断”才会有 ES 1而总中断 EA 1 则需要自己手动加上 //勾选“使能串口中断”会自动生成中断服务函数因此无论是串口还是计时器的中断服务号都不需要记忆3.串口调试助手中com口与单片机烧录所选择的com口不一致三、逻辑正确但无法实现功能1. 代码存在语法错误keil没检查出来if(Ad_Mode 0) //应该用 2. 硬件配置问题板子上没放跳线帽、放错跳线帽、跳线帽松动按键、超声波、NE555频率输出、蜂鸣器、继电器都存在控制其的跳线帽四、NE555频率测量不正常1. 检查按键中是否对P34进行赋值的语句全部注释#include Key.h unsigned char Key_Read() { unsigned char temp 0; P440;P421;P351; //P341; if(P33 0) temp 4; if(P32 0) temp 5; if(P31 0) temp 6; if(P30 0) temp 7; P441;P420;P351; //P341; if(P33 0) temp 8; if(P32 0) temp 9; if(P31 0) temp 10; if(P30 0) temp 11; P441;P421;P350; //P341; if(P33 0) temp 12; if(P32 0) temp 13; if(P31 0) temp 14; if(P30 0) temp 15; //P441;P421;P351;P340; //if(P33 0) temp 16; //if(P32 0) temp 17; //if(P31 0) temp 18; //if(P30 0) temp 19; return temp; }2. 定时器0是否正确配置成计数器模式void Timer0_Init(void) //计数器12.000MHz { AUXR 0x7F; //定时器时钟12T模式 TMOD 0xF0; //将TMOD低四位清零 TMOD | 0x05; //将TMOD低四位设置成0101 TL0 0x00; //设置计数器初始值 TH0 0x00; //设置计数器初始值 TF0 0; //清除TF0标志 TR0 1; //计数器0开始计数 } //以上代码可在STC_ISP“定时器计算器”中生成一部分 //但由于STC_ISP“定时器计算器”中没有配置计数器的选项 //因此需要对生成的代码手动修改3.跳线帽问题P34与SIGNAL是否由跳线帽接在一起五、超声波读数相关问题1.超声波完全无测量示数检查跳线帽是不是没接检查底层附言IAP15F2K61S2只有3个定时器为了节约定时器资源超声波测量常采用PCAprogrammable counter array可编程计数器阵列unsigned char Ultra_Read() { unsigned int temp; CMOD 0x00; CL CH 0; Ultra_Init(); CR 1; while(CF0RX1); CR 0; if(CF 0) { temp CH8|CL; return temp*0.0172; } else { CF 0; return 255; } } //与定时器实现方法相比大致上就是把T(time)换成C(counter)2.超声波读取值总小于4底层 Ultra_Read() 函数中的 temp 变量被定义成 unsigned char 类型3.与4T测评结果相比测量值总少1~3cm受温度等因素的影响超声波的测量示数存在一定误差可对结果手动加上一定值进行校准六、测得温度发生跳变间或从正常值跳至上千原因如果在测温过程中发生中断影响了测温结果解决在测温过程中关闭中断float rd_temper() { unsigned char hign; unsigned char low; init_ds18b20(); Write_DS18B20(0xcc); Write_DS18B20(0x44); init_ds18b20(); Write_DS18B20(0xcc); EA 0; //关闭中断 Write_DS18B20(0xbe); low Read_DS18B20(); hign Read_DS18B20(); EA 1; //开启中断 return (hign8|low)/16.0; }七、某位或某几位数码管显示不稳定发生快速闪烁数码管本来就是闪烁的要使人眼观察不到数码管闪烁发生辉光效应数码管的闪烁周期应该小于10ms出现此问题说明扫描到数码管特定位时停留时间太长可能是中断被人为或异常关闭了较长的一段时间导致扫描不均匀八、ADC测得数字量始终为0ADC需要连续采样采样频率太低容易断电显示数为0。测试发现1. 当把采样函数 Ad_Read() 直接放在main.c的while主循环中情况大大改善2. 在 Ad_Read() 采样之前使IIC先运动起来比如先放一个Read_Rtc()测试发现情况得到解决最后解决更改官方给的IIc底层iic.c#define DELAY_TIME 5 //将10改成5 static void I2C_Delay(unsigned char n) { do { _nop_(); //删成只剩一个_nop_() } while(n--); }九、该更新的量不更新且值为一个自己从没设置的值函数中的局部变量忘了赋初始值其值是不定的如果在函数中从始至终没有对该局部变量进行赋值会导致该问题十、keil:syntax error near“void”代码行附近存在语法错误常见的两种情况1.附近有语句结束时没打符号“”2.void 之前的代码块发生括号不匹配这时既需要检查代码块的最外层前括号也需要检查最外层后括号图中进行的是最外层后括号检查为蓝色说明存在与其匹配的前括号图中进行的是最外层前括号检查为红色说明不存在与其匹配的后括号十一、debug考试时慎用debug用前也要尤其记得对工程进行备份对IAP15F2K61S2使用debug存在很多问题如1.全速运行过程中watch窗口中的变量不会实时更新当停止全速运行时才会进行变量更新2.无法使用条件断点等高级断点比如无法设置触发几次程序中断无法设置触发中断的条件表达式3.以及其他包括卡顿、卡死、连接中断等在内的诸多问题。附言如果发生卡死可以“altctrldel”打开任务管理器关闭keil运行进程但同时可能会发生工程损坏导致工程文件无法打开。我的解决办法是在电脑文件夹资源管理器中删掉该工程除了自己建立.c和.h外的所有文件重新建立新工程在旧工程的User目录中平时可以多用debug建立对程序时序的感知1.可以在watch窗口中对变量进行直接赋值2.合理设置断点并灵活应用5大按钮十二、内存问题以上图片来自西风、左岚“蓝桥杯考点精讲”系列视频之内存管理【蓝桥杯】【单片机】内存管理_哔哩哔哩_bilibili里面还总结了按键的三种长按触发方式、按键长短按互不影响、EEPROM的上电初始校验等考点这些在本次17届蓝桥杯省赛题中均有考察在keil中改Memory Model为Large后要注意对所定义全局的变量进行初始化如果使用Small模式出现内存报错在一些变量的定义前添加idata转data储存为idata存储即可十三、函数封装main.c中内容太多想建立一个.c文件将main.c中的一部分内容封装成函数存放在.c文件中。但想从main.c中挪走的内容调用了许多main.c中定义的全局变量还调用了许多在其他.c文件中定义的函数有点麻烦最好还是放在main.c中针对main.c代码太多太难翻的问题单击鼠标右键在Outlining下选择Show All Outlining可点击代码块左边小正方形进行代码折叠在这里还是说一下之前对函数封装的尝试建立sample.c文件开头引用需要用到的头文件比如“iic.h”等之后正常写函数建立sample.h文件之后是两个步骤变量声明和函数声明把要在sample.c中用到的全局变量全部在sample.h中进行声明注意两点1.每个变量开头要➕“extern”表示该变量不是要在此处进行定义而只是声明一下而已2.不要照搬main.c中的变量定义除了加extern所赋值的部分也要删去只留“extern➕变量类型➕变量名➕”之后又出现一个问题如果我想要创建两个和main.c文件联系非常紧密的.c文件难道在其.h文件中又要把许多涉及到的全局变量都extern一遍吗可以建立一个global.h文件将所有“extern➕变量类型➕变量名➕”放在里面然后再在新建立的.c文件中对global.h进行引用但这又有一个问题main.c中定义的全局变量进行删除或类型修改后需要手动在global.h中进行同步更新还是稍显复杂。以上是新手小白在蓝桥杯备赛中的一些学习总结如有不正敬请指教

更多文章