一、真题



二、模块构建
1.编写初始化函数(init.c)
void Cls_Peripheral(void);
- 关闭led led对应的锁存器由Y4C控制
- 关闭蜂鸣器和继电器
2.编写LED函数(led.c)
void Led_Disp(unsigned char ucLed);
-
将ucLed取反的值赋给P0
-
开启锁存器
-
关闭锁存器
3.编写数码管函数(seg.c)
void Seg_Tran(unsigned char *pucSeg_Buf,unsigned char *pucSeg_Code);
(1)段码转换函数
- 定义两个变量i,j
- for循环加Switch语句进行段码转换,在资源数据包查找段码表,并根据题目要求进行段码转换
- 注意添加空格代表都不显示
- case记得加' '
- 判断是否有 .
void Seg_Disp(unsigned char *pucSeg_Code,unsigned char ucSeg_Pos);
(2)数码管显示函数
- 要对数码管进行消隐
- 显示的位置
- 显示的内容
4.独立按键代码编写
unsigned char Key_Read_BTN(void)
- 有返回值函数(unsigned char)
- if语句判断按键是否按下
- 返回按键所对应的数字
5.超声波代码编写
unsigned char Wave_Recv(void);
- 定义Tx和Rx引脚
- 将定时器里的TR0设置为0
- 定义变量,初始值为10,发射10个周期的波形
- 为了规范,将定时器的初值进行再次赋值
- 再令TR0=1,让定时器开始计时
- 发送10个周期的信号
- 每12us,TF0溢出,将Tx进行异或运算,while循环加分号
- TF0清零
- 关闭定时器,将定时器初值清零,打开定时器进行正计时
- while(RX&&!TF0)如果接收到信号,或TF0溢出,则退出循环
- 退出循环后关闭定时器
- 如果TF0溢出导致退出循环,返回最大值255,否则返回计时时间
- 返回的时间单位是us,需要统一单位,*0.017 进而换算成距离单位为厘米
6.定时器代码编写
void Timer0Init(void);
void Timer1Init(void);
- 定时器0作为超声波定时器,将TR0=0
- 设置定时器0供超声波代码使用,时间为12us,12T,12MHz
- 定时器1作为主定时器,加上ET1=1
7.编写AD/DA代码
unsigned char PCF8591_ADC(void);
void PCF8591_DAC(unsigned char dat);
- 定义SCL,SDA
- 添加"intrins.h"头文件
- 定义变量用于存储采集的电压
- 写入流程:开始--发送写入地址--等待应答--发送电位器地址--等待应答
- 读取流程:开始--发送读取地址--等待应答--变量接收数据--发送应答--终止
- 读取地址为0x91 写入地址为0x90
- 电位器地址为0x43 光敏电阻地址为0x41
三、主函数编写
1.调用初始化,定时器0,定时器1,打开中断总开关,stdio.h
2.编写数码管函数
- 每200ms检测一次
- if模式(Disp_Mode)判断
- 不要忘记调用数码管转换函数(否则数码管会全部点亮)
3. 中断服务函数
- 为各个变量进行自加
- 数码管的动态显示
4.模式界面编写
- 电压数据为unsigned char类型,要转化成浮点数 %4.2f
- 参数界面注意上下限的值
- 测距界面注意超声波状态是否开启
5.ADC函数编写
- 没有规定时间,任意即可
- 将采集来的数据赋值给变量
- 对采集的数据进行判断,看是否在上下限里,从而对超声波设置不同的状态
6.key函数编写
- 定义两个变量
- 时间为20ms
- if判断两个变量是否相等,相等返回
- 不相等进入Switch语句,判断哪个按键被按下
- 最后不要忘记加上Key_Val_Old=Key_Val
- s4按下,Disp_Mode+1对3取模,因为是三个界面进行切换,根据题目要求,判断是否到参数界面,到参数界面,默认选择电压上限
- s6按下,参数值加0.5,注意要判断是否在参数界面
- s7按下,参数值减0.5,注意要判断是否在参数界面
- 注意s4按键按下界面切换的顺序和题目给的顺序不一致
- 由于要求对参数的调整在s4按下后才生效,所以需要增加两个参数,同时记得更改其他按键参数变量
7.超声波函数编写
- 性能指标未规定时间,任意即可
- 在将测距结果赋值给变量前,先判断状态,为0直接返回,不进行测距
8.编写DAC函数
- 判断超声波状态,未开启输出0
- 若开启,判断超声波测距结果,用if else语句来实现相应功能
- 关于呈线性关系的那部分图像,可以用数学方法计算出y=kx+b中的k和b
9.编写led函数
- 性能要求led响应时间小于0.2s
- 判断处于那个界面
- 点亮置1,熄灭置0
- 点亮用|=,熄灭用&=(置1再取反)切换亮灭状态用^=
- 切换亮灭状态,把它放到定时器中断里
四、难点解析
1.按键切换界面的顺序和题目所给顺序不一致
2.调整参数时,参数值不生效,当按键按下时才生效
3.加,减模式的循环,用到了if判断
4.DAC的数据转换------通过数学方法解出来
易错点
将不同函数的计时变量复制粘贴时忘记更改
五、主函数代码
cpp
#include "led.h"
#include "init.h"
#include "seg.h"
#include "key.h"
#include "tim.h"
#include "ultrasonic.h"
#include "iic.h"
#include "stdio.h"
//seg
unsigned char pucSeg_Buf[12],pucSeg_Code[8],ucSeg_Pos=0;
//time
unsigned long ulms=0;
unsigned int uiSeg_Dly=0;
unsigned int uiADC_Dly=0;
unsigned int uiDAC_Dly=0;
unsigned int uiKey_Dly=0;
unsigned int uiLed_Dly=0;
unsigned int uiUltrasonic_Dly=0;
//led
unsigned char ucLed=0x00;
//ADC
unsigned char ucADC=0;
float ADC_Pram_Max=4.5 ,ADC_Pram_Min= 0.5;
float ADC_Pram_Max_temp=4.5 ,ADC_Pram_Min_temp= 0.5;
//key
unsigned char Key_Val=0,Key_Val_Old=0;
//ultrasonic
unsigned char ucDist=0;
unsigned char Ultrasonic_Status=0;
//function
void Seg_Proc(void);
void Led_Proc(void);
void ADC_Proc(void);
void DAC_Proc(void);
void Key_Proc(void);
void Ultrasonic_Proc(void);
//mode
unsigned char Disp_Mode=0;
unsigned char Pram_Mode=0;//0--max 1--min
void main(void)
{
Cls_Peripheral();
Timer0Init();
Timer1Init();
EA=1;
while(1)
{
Seg_Proc();
ADC_Proc();
DAC_Proc();
Key_Proc();
Led_Proc();
Ultrasonic_Proc();
}
}
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==2)
{
sprintf(pucSeg_Buf,"P %3.1f %3.1f",ADC_Pram_Max_temp,ADC_Pram_Min_temp);
}
else
{
if(Ultrasonic_Status==0)
{
sprintf(pucSeg_Buf,"L AAA");
}
else
{
sprintf(pucSeg_Buf,"L %3u",(unsigned int)ucDist);
}
}
Seg_Tran(pucSeg_Buf,pucSeg_Code);
}
void Led_Proc(void)
{
if(uiLed_Dly<100)
return;
uiLed_Dly=0;
if(Disp_Mode==0)
{
ucLed|=0x01;
ucLed&=~0x06;
}
else if(Disp_Mode==1)
{
ucLed|=0x02;
ucLed&=~0x05;
}
else
{
ucLed|=0x04;
ucLed&=~0x03;
}
if(Ultrasonic_Status==1)
{
ucLed^=0x80;
}
else
{
ucLed&=~0x80;
}
Led_Disp(ucLed);
}
void ADC_Proc(void)
{
if(uiADC_Dly<200)
return;
uiADC_Dly=0;
ucADC=PCF8591_ADC();
if((ucADC/51.0>ADC_Pram_Min)&&(ucADC/51.0<ADC_Pram_Max))
{
Ultrasonic_Status=1;
}
else
{
Ultrasonic_Status=0;
}
}
void Key_Proc(void)
{
if(uiKey_Dly<20)
return;
uiKey_Dly=0;
Key_Val=Key_Read_BTN();
if(Key_Val==Key_Val_Old)
return;
switch(Key_Val)
{
case 4:
Disp_Mode=(Disp_Mode+1)%3;
if(Disp_Mode==2)
{
Pram_Mode=0;
ADC_Pram_Max_temp=ADC_Pram_Max;
ADC_Pram_Min_temp=ADC_Pram_Min;
}
else if(Disp_Mode==0)
{
ADC_Pram_Max=ADC_Pram_Max_temp;
ADC_Pram_Min=ADC_Pram_Min_temp;
}
break;
case 5:
if(Disp_Mode==2)
{
Pram_Mode=(Pram_Mode+1)%2;
}
break;
case 6:
if(Disp_Mode==2)
{
if(Pram_Mode==0)
{
if(ADC_Pram_Max_temp==5.0)
{
ADC_Pram_Max_temp=0.5;
}
else
{
ADC_Pram_Max_temp+=0.5;
}
}
else
{
if(ADC_Pram_Min_temp==5.0)
{
ADC_Pram_Min_temp=0.5;
}
else
{
ADC_Pram_Min_temp+=0.5;
}
}
}
break;
case 7:
if(Disp_Mode==2)
{
if(Pram_Mode==0)
{
if(ADC_Pram_Max_temp==0.5)
{
ADC_Pram_Max_temp=5.0;
}
else
{
ADC_Pram_Max_temp-=0.5;
}
}
else
{
if(ADC_Pram_Min_temp==0.5)
{
ADC_Pram_Min_temp=5.0;
}
else
{
ADC_Pram_Min_temp-=0.5;
}
}
}
break;
}
Key_Val_Old=Key_Val;
}
void Ultrasonic_Proc(void)
{
if(uiUltrasonic_Dly<500)
return;
uiUltrasonic_Dly=0;
if(Ultrasonic_Status==0)
return;
ucDist=Wave_Recv();
}
void DAC_Proc(void)
{
if(uiDAC_Dly<200)
return;
uiDAC_Dly=0;
if(Ultrasonic_Status==0)
{
PCF8591_DAC(0);
}
else
{
if(ucDist<=20)
{
PCF8591_DAC(51);
}
else if(ucDist>=80)
{
PCF8591_DAC(255);
}
else
{
PCF8591_DAC(3.4*ucDist-17);
}
}
}
void Time_1(void) interrupt 3
{
ulms++;
uiSeg_Dly++;
uiADC_Dly++;
uiDAC_Dly++;
uiKey_Dly++;
uiLed_Dly++;
uiUltrasonic_Dly++;
if (ulms%2==0)
{
ucSeg_Pos=(ucSeg_Pos+1)%8;
Seg_Disp(pucSeg_Code,ucSeg_Pos);
}
}