欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 【蓝桥杯单片机】第十一届省赛

【蓝桥杯单片机】第十一届省赛

2025/3/13 16:49:08 来源:https://blog.csdn.net/2301_79608998/article/details/146123545  浏览:    关键词:【蓝桥杯单片机】第十一届省赛

一、真题

 

二、创建工程

1.在C盘以外的盘新建文件夹,并在文件夹里面创建两个文件夹Driver 和Project

2.打开keil软件,在新建工程并选择刚刚建好的project文件夹,以准考证号命名

 3.选择对应的芯片型号

 4.选择否,即不创建启动文件

5.勾上生成hex文件的功能

 

6.添加头文件路径

三、模块构建 

1.编写初始化函数(init.c) 

void Cls_Peripheral(void);

  1. 关闭led    led对应的锁存器由Y4C控制
  2. 关闭蜂鸣器和继电器 由Y5C控制

2.编写LED函数(led.c)

void Led_Disp(unsigned char ucLed);

  1. 将ucLed取反的值赋给P0

  2. 开启锁存器 y4

  3. 关闭锁存器 y4

3.编写数码管函数(seg.c)

void Seg_Tran(unsigned char *pucSeg_Buf,unsigned char *pucSeg_Code);

(1)段码转换函数

  • 定义两个变量i,j
  • for循环加Switch语句进行段码转换,在资源数据包查找段码表,并根据题目要求进行段码转换
  • 注意添加空格代表都不显示
  • 注意8+4是C 不是A

void Seg_Disp(unsigned char *pucSeg_Code,unsigned char ucSeg_Pos);

(2)数码管显示函数

  • 要对数码管进行消隐y7
  • 显示的位置 y6
  • 显示的内容y7

4. 编写矩阵键盘代码(key.c)

unsigned char Key_Read_KBD(void);

  1. 有返回值
  2. 16个按键,要用十六位数据类型 unsigned int
  3. 依次将每一列设置为低电平,读取P3的低四位(&0x0f)存储到变量Key_New里,要忘记每个都左移4位,然后记得|
  4. 用Switch语句将按键按下后的值进行判断(Key_New取反 便于理解)
  5. 返回对应按键的值
  6. 不要忘记default 返回都没有按下的值 设为0

5.编写ADC代码

unsigned char PCF8591_ADC(void);

  1.  定义SCL,SDA
  2. 返回值类型
  3. 添加"intrins.h"头文件,接触nop错误
  4. 定义变量用于存储采集的电压
  5. 写入流程:开始--发送写入地址--等待应答--发送电位器地址--等待应答
  6. 读取流程:开始--发送读取地址--等待应答--变量接收数据--发送应答1--终止
  7. 读取地址为0x91 写入地址为0x90
  8. 电位器地址为0x43 
  9. 不要忘记把temp返回

 6.编写AT24C02代码

void EEPROM_Read(unsigned char *pucBuf,unsigned char addr,unsigned char num);

  •  读取流程:开始--发送写入地址--等待应答--发送写入位置-等待应答--开始--发送读取地址--等待应答--while(num--)来逐个存储读取的数据--if判断num是否为0--终止

void EEPROM_Write(unsigned char *pucBuf,unsigned char addr,unsigned char num)

  • 开始--发送写入地址--等待应答--发送写入位置--等待应答-- while(num--)来逐个将数据写入(加入延时保证稳定性)--终止

7.定时器函数编写

void Timer0Init(void); 

  1. 在sti-isp软件中生成定时长度为1ms的c代码,直接复制
  2. 不要忘记打开定时器0的开关和定时器总开关

 四、主函数代码

1.添加好所有头文件在主函数和工程文件夹中

2.外设初始化,定时器初始化,打开中断总开关

3.数码管函数编写

  • 定义数组和变量,数组分别为12为和8位,不加*  变量赋初值为0
  • 编写Seg_Proc();函数
  • 添加时间变量在定时器0中断进行自加
  • 200ms
  • 动态显示添加到中断里
  • 判断模式
  • 数码管转换函数不要忘

4.ADC函数编写

  • 时间200
  • 将读取的值赋值给变量,实际的值需要除以51.0是真实电压值

5.按键函数编写

  • 不用NE555时,不要短接,否则按键会失效

6.led函数编写

  •  200ms
  • 最后不要忘记调用led显示函数

五、难点解析

1.关于EEPROM 的断电保存

2.触发条件

3.指示灯 用到了ulms

4.无效按键的触发 

六、主函数代码

#include <stdio.h>
#include "seg.h"
#include "led.h"
#include "init.h"
#include "key.h"
#include "iic.h"
#include "tim.h"
//Seg
unsigned char pucSeg_Buf[12],pucSeg_Code[8],ucSeg_Pos=0;
//ADC
unsigned char ucADC=0;
float ADC_Pram=0;
unsigned int uicount=0;
unsigned char ucADC_Old=0;
//led
unsigned char ucLed=0;
//key
unsigned char Key_Val=0,Key_Val_Old=0;
unsigned int uiError=0;
//EEPROM
unsigned char EEPROM_Buf[2];
//timer
unsigned long ulms=0;
unsigned long ulled=0;
unsigned int uiSeg_Dly=0;
unsigned int uiADC_Dly=0;
unsigned int uiKey_Dly=0;
unsigned int uiLed_Dly=0;//function
void Seg_Proc(void);
void ADC_Proc(void);
void Key_Proc(void);
void Led_Proc(void);//mode
unsigned char Disp_Mode=0;void main(void)
{Cls_Peripheral();EEPROM_Read(EEPROM_Buf,0x00,1);ADC_Pram=EEPROM_Buf[0]/10.0;Timer0Init();EA=1;while(1){Seg_Proc();ADC_Proc();Key_Proc();Led_Proc();}
}
void Led_Proc(void)
{if(uiLed_Dly<200)return;uiLed_Dly=0;if(((ucADC/51.0)<ADC_Pram)&&(ulms-ulled>5000)){ucLed|=0x01;}else{ucLed&=~0x01;}if(uicount%2==0){ucLed&=~0x02;}else{ucLed|=0x02;}if(uiError>=3){ucLed|=0x04;}else{ucLed&=~0x04;}Led_Disp(ucLed);
}void Seg_Proc(void)
{if(uiSeg_Dly<200)return;uiSeg_Dly=0;if(Disp_Mode==0){sprintf(pucSeg_Buf,"U    %4.2f",ucADC/51.0);}else if(Disp_Mode==1){sprintf(pucSeg_Buf,"P    %4.2f",ADC_Pram);}else{sprintf(pucSeg_Buf,"N%7u",uicount);}Seg_Tran(pucSeg_Buf,pucSeg_Code);
}
void ADC_Proc(void)
{if(uiADC_Dly<500)return;uiADC_Dly=0;ucADC=PCF8591_ADC();if(((ucADC_Old/51.0)>ADC_Pram)&&((ucADC/51.0)<=ADC_Pram)){uicount++;ulled=ulms;}if(((ucADC_Old/51.0)<ADC_Pram)&&((ucADC/51.0)>=ADC_Pram)){ulled=ulms;}ucADC_Old=ucADC;
}
void Key_Proc(void)
{if(uiKey_Dly<20)return;uiKey_Dly=0;Key_Val=Key_Read_KBD();if(Key_Val==Key_Val_Old)return;switch (Key_Val){case 12:uiError=0;Disp_Mode=(Disp_Mode+1)%3;if(Disp_Mode==2){EEPROM_Buf[0]=(unsigned char)(ADC_Pram*10);EEPROM_Write(EEPROM_Buf,0x00,1);}break;case 13:if(Disp_Mode==2){uiError=0;uicount=0;}else{uiError++;}case 16:if(Disp_Mode==1){uiError=0;if(ADC_Pram>=5){ADC_Pram=0;}else{ADC_Pram+=0.5;}}else{uiError++;}break;case 17:if(Disp_Mode==1){uiError=0;if(ADC_Pram<=0.0){ADC_Pram=5.0;}else{ADC_Pram-=0.5;}}else{uiError++;}break;}Key_Val_Old=Key_Val;
}
void Time_0(void) interrupt 1
{ulms++;uiSeg_Dly++;uiADC_Dly++;uiKey_Dly++;uiLed_Dly++;if(ulms%2==0){ucSeg_Pos=(ucSeg_Pos+1)%8;Seg_Disp(pucSeg_Code,ucSeg_Pos);}
}

热搜词