当前位置:   article > 正文

蓝桥杯十四届单片机国赛试题及代码_第十四届蓝桥杯单片机国赛

第十四届蓝桥杯单片机国赛

    今年十四届单片机国赛试题在程序题设计方面难度有所下降,但选择题没有了以往可以在手册中可以找到的单片机类选择题,选择题难度较高,因此想获得一个不错的成绩,需要在选择题方面有所加强

试题展示8320c8da8acb4ae780cd9aabd6d58a44.jpg696586bcf93c495a9694e4b41c47d5bb.jpg

e74256a9696b4bff800b566c8ec22458.jpg

a4611a7298574382aad1b56888fb4965.jpg

ed8a1581eab64487af699e59744eb62d.jpg

39536be7845d44d59de9dc29ccf3f8e5.jpg

8c9a706801a94367a0c15d58a3d9bfe9.jpg

设计说明 

此次国赛采用了温度传感器DS18B20模块,LED模块,按键模块,Pcf8591DAC模块,iic,超声波模块,外设模块不算多,没有13届的定时器分配问题,思路很容易理清。

个人觉得难点在于S8.9两个按键的处理,最好是判断两个同时按下做一个标记在超过两秒后进行初始化功能,因为在松手时不一定能准确控制在10ms内。

矩阵按键模块

  1. #include "bsp_key.h"
  2. unsigned char Key_Read(void)
  3. {
  4. unsigned int Key_New;
  5. unsigned char Key_Value;
  6. P44 = 0;P42 = 1;P35 = 1;P34 = 1;
  7. Key_New = P3&0X0F;
  8. P44 = 1;P42 = 0;P35 = 1;P34 = 1;
  9. Key_New = (Key_New<<4)|(P3&0X0F);
  10. P44 = 1;P42 = 1;P35 = 0;P34 = 1;
  11. Key_New = (Key_New<<4)|(P3&0X0F);
  12. P44 = 1;P42 = 1;P35 = 1;P34 = 0;
  13. Key_New = (Key_New<<4)|(P3&0X0F);
  14. switch(~Key_New)
  15. {
  16. case 0x8000:Key_Value = 4;break;
  17. case 0x4000:Key_Value = 5;break;
  18. case 0x2000:Key_Value = 6;break;
  19. case 0x1000:Key_Value = 7;break;
  20. case 0x0800:Key_Value = 8;break;
  21. case 0x0400:Key_Value = 9;break;
  22. case 0x0200:Key_Value = 10;break;
  23. case 0x0100:Key_Value = 11;break;
  24. case 0x0080:Key_Value = 12;break;
  25. case 0x0040:Key_Value = 13;break;
  26. case 0x0020:Key_Value = 14;break;
  27. case 0x0010:Key_Value = 15;break;
  28. case 0x0008:Key_Value = 16;break;
  29. case 0x0004:Key_Value = 17;break;
  30. case 0x0002:Key_Value = 18;break;
  31. case 0x0001:Key_Value = 19;break;
  32. case 0x0c00:Key_Value = 89;break;
  33. default :Key_Value = 0;
  34. }
  35. return Key_Value;
  36. }

数码管显示模块

  1. #include "bsp_seg.h"
  2. void Seg_Tran(unsigned char *seg_string,unsigned char *seg_buf)
  3. {
  4. unsigned char i = 0;
  5. unsigned char j = 0;
  6. unsigned char temp;
  7. for(i = 0;i<= 7;i++,j++)
  8. {
  9. switch(seg_string[j])
  10. {
  11. case '0':temp = 0xc0;break;
  12. case '1':temp = 0xf9;break;
  13. case '2':temp = 0xa4;break;
  14. case '3':temp = 0xb0;break;
  15. case '4':temp = 0x99;break;
  16. case '5':temp = 0x92;break;
  17. case '6':temp = 0x82;break;
  18. case '7':temp = 0xf8;break;
  19. case '8':temp = 0x80;break;
  20. case '9':temp = 0x90;break;
  21. case 'A':temp = 0x88;break;
  22. case 'B':temp = 0x83;break;
  23. case 'C':temp = 0xc6;break;
  24. case 'D':temp = 0xa1;break;
  25. case 'E':temp = 0x86;break;
  26. case 'F':temp = 0x8e;break;
  27. case ' ':temp = 0xff;break;
  28. case '-':temp = 0xbf;break;
  29. case 'H':temp = 0x89;break;
  30. case 'L':temp = 0xc7;break;
  31. case 'N':temp = 0xc8;break;
  32. case 'P':temp = 0x8c;break;
  33. case 'U':temp = 0xc1;break;
  34. default:temp = 0xff;break;
  35. }
  36. if(seg_string[j+1] == '.')
  37. {
  38. temp &= 0x7f;
  39. j++;
  40. }
  41. seg_buf[i] = temp;
  42. }
  43. }
  44. void Seg_Disp(unsigned char *seg_buf,unsigned char pos)
  45. {
  46. P0 = 0XFF;
  47. P2 = P2 & 0X1F |0XE0;
  48. P2 &= 0X1F;
  49. P0 = 1<<pos;
  50. P2 = P2 & 0X1F |0Xc0;
  51. P2 &= 0X1F;
  52. P0 = seg_buf[pos];
  53. P2 = P2 & 0X1F |0XE0;
  54. P2 &= 0X1F;
  55. }

DS18B20模块

  1. unsigned int rd_temperature(void)
  2. {
  3. unsigned char low,high;
  4. init_ds18b20();
  5. Write_DS18B20(0xcc);//跳过rom只有一个温度传感器
  6. Write_DS18B20(0x44);//转换温度
  7. init_ds18b20();
  8. Write_DS18B20(0xcc);
  9. Write_DS18B20(0xbe); //将温度依次返回
  10. low = Read_DS18B20();//先读低温度
  11. high = Read_DS18B20();//先读低温度
  12. return((high<<8)|low);
  13. }

超声波模块

  1. #include "bsp_ultrasonic.h"
  2. sbit TX = P1^0;
  3. sbit RX = P1^1;
  4. void ultrasonic_Timer0init(void)
  5. {
  6. AUXR &= 0x7F; //定时器时钟12T模式
  7. TMOD &= 0xF0; //设置定时器模式
  8. TL0 = 0xF4; //设置定时初值
  9. TH0 = 0xFF; //设置定时初值
  10. TF0 = 0; //清除TF0标志
  11. TR0 = 0; //定时器0不开始计时
  12. }
  13. unsigned char ultrasonic_rec(void)
  14. {
  15. unsigned char num = 10;//与定时器12mhz形成40hz的超声波
  16. unsigned char Distance;
  17. TX = 0;
  18. TL0 = 0xF4; //设置定时初值
  19. TH0 = 0xFF; //设置定时初值
  20. TR0 = 1;
  21. while(num--)
  22. {
  23. while(!TF0);
  24. TX ^= 1;
  25. TF0 = 0;
  26. }
  27. TR0 = 0;
  28. TL0 = 0; //此时装0时将定时称0.017换算距离
  29. TH0 = 0; //设置定时初值
  30. TR0 = 1;
  31. while(RX && (~TF0));//RX平时为1变0是接收到40hz脉冲
  32. TR0 = 0;
  33. if(TF0 == 1)//距离溢出
  34. {
  35. Distance = 255;
  36. TF0 = 0;
  37. }
  38. else
  39. {
  40. Distance = (((TH0<<8)|TL0)*0.017);
  41. TF0 = 0;
  42. }
  43. return Distance;
  44. }

显示定时器模块

  1. #include "Timer.h"
  2. void Timer1Init(void) //1毫秒@12.000MHz
  3. {
  4. AUXR &= 0xBF; //定时器时钟12T模式
  5. TMOD &= 0x0F; //设置定时器模式
  6. TL1 = 0x18; //设置定时初值
  7. TH1 = 0xFC; //设置定时初值
  8. TF1 = 0; //清除TF1标志
  9. TR1 = 1; //定时器1开始计时
  10. ET1 = 1;
  11. }

LED及继电器模块

  1. #include "bsp_led.h"
  2. void Led_Disp(unsigned char ucLed)
  3. {
  4. P0 = (~ucLed);
  5. P2 = P2 & 0X1F |0X80;
  6. P2 &= 0X1F;
  7. }
  8. void Relay(unsigned char relay)
  9. {
  10. P0 = relay;
  11. P2 = P2 & 0X1F |0Xa0;
  12. P2 &= 0X1F;
  13. }

DAC模块

  1. #include "bsp_iic.h"
  2. #define DELAY_TIME 5
  3. sbit SDA = P2^1;
  4. sbit SCL = P2^0;
  5. //
  6. void IIC_Delay(unsigned char i)
  7. {
  8. do{_nop_();}
  9. while(i--);
  10. }
  11. //
  12. void IIC_Start(void)
  13. {
  14. SDA = 1;
  15. SCL = 1;
  16. IIC_Delay(DELAY_TIME);
  17. SDA = 0;
  18. IIC_Delay(DELAY_TIME);
  19. SCL = 0;
  20. }
  21. //
  22. void IIC_Stop(void)
  23. {
  24. SDA = 0;
  25. SCL = 1;
  26. IIC_Delay(DELAY_TIME);
  27. SDA = 1;
  28. IIC_Delay(DELAY_TIME);
  29. }
  30. //
  31. void IIC_SendAck(bit ackbit)
  32. {
  33. SCL = 0;
  34. SDA = ackbit;
  35. IIC_Delay(DELAY_TIME);
  36. SCL = 1;
  37. IIC_Delay(DELAY_TIME);
  38. SCL = 0;
  39. SDA = 1;
  40. IIC_Delay(DELAY_TIME);
  41. }
  42. //
  43. bit IIC_WaitAck(void)
  44. {
  45. bit ackbit;
  46. SCL = 1;
  47. IIC_Delay(DELAY_TIME);
  48. ackbit = SDA;
  49. SCL = 0;
  50. IIC_Delay(DELAY_TIME);
  51. return ackbit;
  52. }
  53. //
  54. void IIC_SendByte(unsigned char byt)
  55. {
  56. unsigned char i;
  57. for(i=0; i<8; i++)
  58. {
  59. SCL = 0;
  60. IIC_Delay(DELAY_TIME);
  61. if(byt & 0x80) SDA = 1;
  62. else SDA = 0;
  63. IIC_Delay(DELAY_TIME);
  64. SCL = 1;
  65. byt <<= 1;
  66. IIC_Delay(DELAY_TIME);
  67. }
  68. SCL = 0;
  69. }
  70. //
  71. unsigned char IIC_RecByte(void)
  72. {
  73. unsigned char i, da;
  74. for(i=0; i<8; i++)
  75. {
  76. SCL = 1;
  77. IIC_Delay(DELAY_TIME);
  78. da <<= 1;
  79. if(SDA) da |= 1;
  80. SCL = 0;
  81. IIC_Delay(DELAY_TIME);
  82. }
  83. return da;
  84. }
  85. void Pcf8591_DAC(float Dac_data)
  86. {
  87. IIC_Start();
  88. IIC_SendByte(0x90);//选择选择pcf8591写东西模式
  89. IIC_WaitAck();
  90. IIC_SendByte(0x41);//选择写0x41通道
  91. IIC_WaitAck();
  92. IIC_SendByte(Dac_data);//发送写的内容
  93. IIC_WaitAck();
  94. IIC_Stop();//停止对iic的控制
  95. }

初始化

  1. #include "bsp_init.h"
  2. void Clc_Peripheral(void)
  3. {
  4. P0 = 0XFF;
  5. P2 = P2 & 0X1F |0X80;
  6. P2 &= 0X1F;
  7. P0 = 0X00;
  8. P2 = P2 & 0X1F |0XA0;
  9. P2 &= 0X1F;
  10. }

主函数

  1. #include "STC15F2K60S2.H"
  2. #include "bsp_init.h"
  3. #include "Timer.h"
  4. #include "bsp_led.h"
  5. #include "bsp_key.h"
  6. #include "bsp_seg.h"
  7. #include "stdio.h"
  8. #include "bsp_onewire.h"
  9. #include "bsp_iic.h"
  10. #include "bsp_ultrasonic.h"
  11. //程序减速
  12. unsigned int Seg_Slow_Down = 0;
  13. unsigned int Key_Slow_Down = 0;
  14. unsigned int Led_Slow_Down = 0;
  15. ///三大服务模块
  16. void Key_Proc(void);
  17. void Seg_Proc(void);
  18. void Led_Proc(void);
  19. void Delay500ms() //@12.000MHz
  20. {
  21. unsigned char i, j, k;
  22. _nop_();
  23. _nop_();
  24. i = 23;
  25. j = 205;
  26. k = 120;
  27. do
  28. {
  29. do
  30. {
  31. while (--k);
  32. } while (--j);
  33. } while (--i);
  34. }
  35. //按键
  36. unsigned char Key_Value,Key_Down,Key_Old,Key_Up;
  37. //数码管
  38. unsigned char seg_string[10];
  39. unsigned char seg_buf[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
  40. unsigned char pos;
  41. //LED
  42. unsigned char ucLed;
  43. //其他变量
  44. float Temperature;//测得的距离
  45. float Distance;//测得的距离
  46. float Distance_Disp;//调整后的距离
  47. bit Distance_M__CM_flag = 0;//CM和M标志 0为初始CM
  48. unsigned char Inter_Face = 0x11;//界面标号 0x11测距界面 0x21参数界面-距离参数 0x22参数界面-温度参数 0x31校准值界面 0x32介质传输速度界面 0x33DAC下限界面
  49. unsigned long ms_Tick = 0;
  50. unsigned long Key_ms_Tick = 0;
  51. unsigned long xdata Data_record_ms_Tick = 0;
  52. unsigned char Distance_DAC;
  53. unsigned char Distance_Canshu = 40;//距离参数
  54. unsigned char Temperature_Canshu = 30;//温度参数
  55. int Distance_calibration = 0;//校准值
  56. unsigned int xdata Ultrasonic_medium = 340;//介质传播速度
  57. float DAC_Low_Vlaue = 1.0;//DAC下限
  58. bit Key_89_2s_flag = 0;
  59. bit Data_record = 0;
  60. bit DAC_flag = 0;
  61. float DAC_Data;
  62. void main(void)
  63. {
  64. Clc_Peripheral();
  65. Timer1Init();
  66. rd_temperature();
  67. Delay500ms();
  68. EA = 1;
  69. ultrasonic_Timer0init();
  70. while(1)
  71. {
  72. Key_Proc();
  73. Seg_Proc();
  74. Led_Proc();
  75. }
  76. }
  77. void tm1_isr() interrupt 3
  78. {
  79. ms_Tick++;
  80. if(++Key_Slow_Down == 10)Key_Slow_Down = 0;
  81. if(++Seg_Slow_Down == 70)Seg_Slow_Down = 0;
  82. if(++Led_Slow_Down == 100)Led_Slow_Down = 0;
  83. else if(((Inter_Face >> 4) == 0x03)&&(ms_Tick % 100) == 0)
  84. {
  85. ucLed &= 0x7f;
  86. ucLed ^= 0x01;
  87. }
  88. Led_Disp(ucLed);
  89. Seg_Disp(seg_buf,pos);
  90. if(++pos == 8)pos = 0;
  91. }
  92. void Key_Proc(void)
  93. {
  94. if(Key_Slow_Down) return;
  95. Key_Slow_Down = 1;
  96. Key_Value = Key_Read();
  97. Key_Down = Key_Value & (Key_Old ^ Key_Value);//按键按下
  98. Key_Up = ~Key_Value & (Key_Old ^ Key_Value);//按键弹起
  99. Key_Old = Key_Value;
  100. if(Key_Down)
  101. {
  102. if(Key_Down == 89)Key_89_2s_flag = 1;
  103. Key_ms_Tick = ms_Tick;
  104. }
  105. if(((ms_Tick - Key_ms_Tick) <= 2000)&&(Data_record == 0))//短按 按下2s内
  106. {
  107. switch(Key_Up)
  108. {
  109. case 4:
  110. if((Inter_Face >> 4) == 0x01) Inter_Face = 0x21;
  111. else if((Inter_Face >> 4) == 0x02) Inter_Face = 0x31;
  112. else if((Inter_Face >> 4) == 0x03) Inter_Face = 0x11;
  113. break;
  114. case 5:
  115. if(Inter_Face == 0x11)Distance_M__CM_flag ^= 1;
  116. else if(Inter_Face == 0x21)Inter_Face = 0x22;
  117. else if(Inter_Face == 0x22)Inter_Face = 0x21;
  118. else if(Inter_Face == 0x31)Inter_Face = 0x32;
  119. else if(Inter_Face == 0x32)Inter_Face = 0x33;
  120. else if(Inter_Face == 0x33)Inter_Face = 0x31;
  121. break;
  122. case 8://按键++判断 以及记录功能
  123. if(Inter_Face == 0x11)
  124. {
  125. Data_record = 1;
  126. Data_record_ms_Tick = ms_Tick;
  127. }
  128. else if(Inter_Face == 0x21)
  129. {
  130. Distance_Canshu += 10;
  131. if(Distance_Canshu == 100)Distance_Canshu = 90;
  132. }
  133. else if(Inter_Face == 0x22)
  134. {
  135. Temperature_Canshu += 1;
  136. if(Temperature_Canshu == 81)Temperature_Canshu = 80;
  137. }
  138. else if(Inter_Face == 0x31)
  139. {
  140. Distance_calibration += 5;
  141. if(Distance_calibration == 95)Distance_calibration = 90;
  142. }
  143. else if(Inter_Face == 0x32)
  144. {
  145. Ultrasonic_medium += 10;
  146. if(Ultrasonic_medium == 10000)Ultrasonic_medium = 9990;
  147. }
  148. else if(Inter_Face == 0x33)
  149. {
  150. DAC_Low_Vlaue += 0.1;
  151. if(DAC_Low_Vlaue >= 2.0)DAC_Low_Vlaue = 2.0;
  152. }
  153. break;
  154. case 9://按键--判断 以及DAC输出功能
  155. if(Inter_Face == 0x11)DAC_flag = 1;
  156. else if(Inter_Face == 0x21)
  157. {
  158. Distance_Canshu -= 10;
  159. if(Distance_Canshu == 0)Distance_Canshu = 10;
  160. }
  161. else if(Inter_Face == 0x22)
  162. {
  163. Temperature_Canshu -= 1;
  164. if(Temperature_Canshu == 255)Temperature_Canshu = 0;
  165. }
  166. else if(Inter_Face == 0x31)
  167. {
  168. Distance_calibration -= 5;
  169. if(Distance_calibration == -95)Distance_calibration = -90;
  170. }
  171. else if(Inter_Face == 0x32)
  172. {
  173. Ultrasonic_medium -= 10;
  174. if(Ultrasonic_medium == 0)Ultrasonic_medium = 10;
  175. }
  176. else if(Inter_Face == 0x33)
  177. {
  178. DAC_Low_Vlaue -= 0.1;
  179. if(DAC_Low_Vlaue <= 0.1)DAC_Low_Vlaue = 0.1;
  180. }
  181. break;
  182. }
  183. }
  184. else if(((ms_Tick - Key_ms_Tick) > 2000)&&(Key_89_2s_flag == 1))//长按判断标志是否为1
  185. {
  186. ucLed ^=0xff;
  187. Key_89_2s_flag = 0;
  188. Distance_M__CM_flag = 0;
  189. Distance_Canshu = 40;
  190. Temperature_Canshu = 30;
  191. Distance_calibration = 0;
  192. Ultrasonic_medium = 340;
  193. DAC_Low_Vlaue = 1.0;
  194. }
  195. if((Data_record == 1)&&((ms_Tick - Data_record_ms_Tick) < 6000))
  196. {
  197. if((ms_Tick%1000) == 0)Distance_DAC = ultrasonic_rec();
  198. }
  199. else if((Data_record == 1)&&((ms_Tick - Data_record_ms_Tick) > 6000))Data_record = 0;
  200. }
  201. void Seg_Proc(void)
  202. {
  203. if(Seg_Slow_Down) return;
  204. Seg_Slow_Down = 1;
  205. Temperature = (rd_temperature()/16.0);
  206. Distance = ultrasonic_rec();
  207. Distance_Disp = ((Ultrasonic_medium/340.0)*Distance+Distance_calibration);//将标准环境下的速度进行调整和校准
  208. //*****DAC输出*****
  209. if(Distance_Disp >= 90)DAC_Data = 255;
  210. else if(Distance_Disp <= 10)DAC_Data = 51;
  211. else if((Distance_Disp > 10)&&(Distance_Disp < 90))DAC_Data = 51*(((5-DAC_Low_Vlaue)/80.0)*Distance_Disp+(DAC_Low_Vlaue - ((5-DAC_Low_Vlaue)/8.0)));
  212. if(DAC_flag == 1)Pcf8591_DAC(DAC_Data);
  213. //****************
  214. switch(Inter_Face)
  215. {
  216. case 0x11:
  217. if(Distance_M__CM_flag == 0)sprintf(seg_string,"%03.1f-%4d",Temperature,(unsigned int)Distance_Disp); //cm
  218. else if(Distance_M__CM_flag == 1)sprintf(seg_string,"%03.1f-%4.2f",Temperature,(Distance_Disp/100.0)); //m
  219. break;
  220. case 0x21:
  221. sprintf(seg_string,"P1 %02d",(unsigned int)Distance_Canshu);//距离参数界面
  222. break;
  223. case 0x22:
  224. sprintf(seg_string,"P2 %02d",(unsigned int)Temperature_Canshu);//温度参数界面
  225. break;
  226. case 0x31:
  227. sprintf(seg_string,"F1 %3d",Distance_calibration);//距离校准界面
  228. break;
  229. case 0x32:
  230. sprintf(seg_string,"F2 %4d",Ultrasonic_medium);//介质速度界面
  231. break;
  232. case 0x33:
  233. sprintf(seg_string,"F2 %2.1f",DAC_Low_Vlaue);//dac下限界面
  234. break;
  235. }
  236. Seg_Tran(seg_string,seg_buf);
  237. }
  238. void Led_Proc(void)//Led 和继电器
  239. {
  240. if(Led_Slow_Down) return;
  241. Led_Slow_Down = 1;
  242. if(Inter_Face == 0x11)
  243. {
  244. if(Distance_Disp > 255)ucLed = 0xff;
  245. else if(Distance_Disp < 255)
  246. {
  247. ucLed = Distance_Disp;
  248. }
  249. }
  250. else if((Inter_Face >> 4) == 0x02)//L8
  251. {
  252. ucLed &= 0x0;
  253. ucLed |= 0x80;
  254. }
  255. //继电器
  256. if((Distance_Disp < (Distance_Canshu+5))&&(Distance_Disp > (Distance_Canshu -5))&&(Temperature <= Temperature_Canshu))Relay(0x10);//L10
  257. else Relay(0x0);
  258. }

功能演示

 B站视频连接: https://b23.tv/ixYMJaB

免责声明:函数模块采用蚂蚁工程科技子函数模块,代码仅供学习未商用,如有侵权请联系。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/350356
推荐阅读
相关标签
  

闽ICP备14008679号