在码字之前,我们按照常理先上题目。
我个人觉得,在做到这套程序题的时候,我们先不要急着想着每个模块怎么去做,我们需要花上一两分钟左右的时间将大致内容浏览一下。接着重点主要看题目中的模块硬件框图,根据模块硬件框图,确定自己需要用到哪些模块,然后在新建的代码文件框架构建好。这部分内容,我在之前的电子钟的分析中讲过,如何搭建整体模块,然后框架中细化内容。
这里我们分析完所需的模块后,进入眼帘的是数码管的显示。我借阅过大多数蓝桥杯单片机比赛者的代码,自己总结了一套针对蓝桥杯数码管显示的处理方法—数组。那就是将数码管显示,数据处理,其他模块功能独立化开来,避免脚踩西瓜皮,走到哪写到哪。
接下里,我就以这套国赛为例,仔细分析。
1.数码管显示:
数码管实际上只需要显示四种不同的界面,前三种不好归为一类,后三种都关于参数界面的显示,而且显示上几乎一模一样。
所以初始定义数组的时候我们可以更具数码管显示图,大致定义如下:
code uchar smg_duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xc6,0x86,0x8c,0xff};//数码管段选
uchar tab_1[]={0,0,10,0,0,10,0,0}; //数据界面1图
uchar tab_2[]={11,14,14,14,14,0,0,0};//数据界面2图
uchar tab_3[]={12,14,0,0,0,14,14,0}; //数据界面3图
uchar tab_4[]={13,0,14,14,14,14,0,0};//参数界面界图
2.数据处理(依据不同的情况进行):
void Data_process() //数据处理
{
if(guang>20) g_flag=0;
else g_flag=1;
tab_1[0]=rtc_time[0]/10;
tab_1[1]=rtc_time[0]%10;
tab_1[3]=rtc_time[1]/10;
tab_1[4]=rtc_time[1]%10;
tab_1[6]=rtc_time[2]/10;
tab_1[7]=rtc_time[2]%10;
tab_2[5]=wendu/100;
tab_2[6]=wendu/100/10;
tab_2[7]=wendu%10;
tab_3[2]=guang/100;
tab_3[3]=guang/100/10;
tab_3[4]=guang%10;
tab_3[7]=g_flag;
if(parameter_face0) { tab_4[1]=1;tab_4[6]=t_c/10;tab_4[7]=t_c%10;}
if(parameter_face1) { tab_4[1]=2;tab_4[6]=w_c/10;tab_4[7]=w_c%10;}
if(parameter_face==2) { tab_4[1]=3;tab_4[6]=14;tab_4[7]=d_c;}
}
大家不需要在意这些未知的定义变量,大家的目光是需要看我对对应的数组的处理。我这种用数组确定数码管显示,处理数据的方法,是独立开来的,编写完后,可以直接放在定时中断中。
这里大致概括思路:数码管显示+数据处理+LED数据处理+外设+键盘扫描
接下来直接上代码:
为了便于需要的人下载,完整的代码我会再以资源的形式上传。
Main.c
#include <STC15F2K60S2.H>
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
#define Latch(x,y) {P0=y;P2=(P2&0x1f)|(x<<4);P2&=0x1f;}
#define key_state0 0 //检测按键是否按下;
#define key_state1 1 //检测是否抖动;
#define key_state2 2 //检测按键是否松开
code uchar smg_duan[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xc6,0x86,0x8c,0xff};//数码管段选
uchar rtc_time[]={
16,59,50};
uchar tab_1[]={
0,0,10,0,0,10,0,0};
uchar tab_2[]={
11,14,14,14,14,0,0,0};
uchar tab_3[]={
12,14,0,0,0,14,14,0};
uchar tab_4[]={
13,0,14,14,14,14,0,0};
uchar inter_face=0; //界面
uchar data_face=0; //数据界面
uchar parameter_face=0;//参数界面
uchar t_c=17; //时间参数
uchar w_c=25; //温度参数
uchar d_c=4;//灯参数
uint wendu; //温度存放值
uint guang; //光强存放值
uchar g_flag; //光强标志
uchar Ucled=0;//led灯
uchar fg_1; //暗三秒标志
uchar fg_2; //亮三秒标志
void System_init() //系统初始化
{
Latch(10,0);
Latch(14,0xff);
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
uchar Key_scan() //矩阵键盘,状态机切换扫描
{
uchar key_value;
static char key_state=0;
uchar key_return=0 ;
uchar key_1,key_2;
P44=1;P42=1;P3=0xf0;
if(P44==0) key_1=0x70;
if(P42==0) key_1=0xb0;
if(P35==0) key_1=0xd0;
if(P34==0) key_1=0xe0;
if((P44==1)&&(P42==1)&&(P35==1)&&(P34==1)) key_1=0xf0;
P44=0;P42=0;P3=0x0f;
if(P30==0) key_2=0x0e;
if(P31==0) key_2=0x0d;
if(P32==0) key_2=0x0b;
if(P33==0) key_2=0x07;
if((P3&0x0f)==0x0f) key_2=0x0f;
key_value=key_1|key_2;
switch(key_state)
{
case key_state0 : if(key_value!=0xff) key_state=key_state1;
break;
case key_state1:
if(key_value!=0xff)
{
if(key_value==0x77) key_return=4;
if(key_value==0x7b) key_return=5;
if(key_value==0xb7) key_return=8;
if(key_value==0xbb) key_return=9;
key_state=key_state2;
}
else key_state=key_state0;
break;
case key_state2:
if(key_value==0xff) key_state=key_state0;
break;
}
return key_return;
}
void Data_process() //数据处理
{
if(guang>20) g_flag=0;
else g_flag=1;
tab_1[0]=rtc_time[0]/10;
tab_1[1]=rtc_time[0]%10;
tab_1[3]=rtc_time[1]/10;
tab_1[4]=rtc_time[1]%10;
tab_1[6]=rtc_time[2]/10;
tab_1[7]=rtc_time[2]%10;
tab_2[5]=wendu/100;
tab_2[6]=wendu/100/10;
tab_2[7]=wendu%10;
tab_3[2]=guang/100;
tab_3[3]=guang/100/10;
tab_3[4]=guang%10;
tab_3[7]=g_flag;
if(parameter_face==0) {
tab_4[1]=1;tab_4[6]=t_c/10;tab_4[7]=t_c%10;}
if(parameter_face==1) {
tab_4[1]=2;tab_4[6]=w_c/10;tab_4[7]=w_c%10;}
if(parameter_face==2) {
tab_4[1]=3;tab_4[6]=14;tab_4[7]=d_c;}
}
void Smg_display() //数码管显示函数
{
static uchar discom;
static uchar xiao;
Latch(14,0xff);
Latch(12,1<<discom);
if(inter_face==0&&data_face==0) {
Latch(14,smg_duan[tab_1[discom]]);}
if(inter_face==0&&data_face==1) {
if(discom==6) xiao=0x7f;else xiao=0xff; Latch(14,smg_duan[tab_2[discom]]&xiao);}
if(inter_face==0&&data_face==2) {
if(discom==2) xiao=0x7f;else xiao=0xff;Latch(14,smg_duan[tab_3[discom]]&xiao);}
if(inter_face==1) {
Latch(14,smg_duan[tab_4[discom]]);}
if(++discom==8) discom=0;
}
void Key_process(uchar key_value)
{
static uchar m=0;
static uchar n=0;
static uchar k=0;
switch(key_value)
{
case 4: if(m==0) {
inter_face=1;m=1;parameter_face=0;} else {
inter_face=0;m=0;data_face=0;}break;
case 5: if(inter_face==0) {
if(++n==3){
n=0;} if(n==0) data_face=0;if(n==1) data_face=1;if(n==2) data_face=2; }
if(inter_face==1) {
if(++k==3){
k=0;} if(k==0) parameter_face=0;if(k==1) parameter_face=1;if(k==2) parameter_face=2;}
break;
case 8: if(inter_face==1) {
switch(parameter_face)
{
case 0: if(t_c==0)t_c=0; else t_c--;break;
case 1: if(w_c==0) w_c=0; else w_c--;break;
case 2: if(d_c==4) d_c=4; else d_c--;break;
}
} break;
case 9: if(inter_face==1) {
switch(parameter_face)
{
case 0: if(t_c==23)t_c=23; else t_c++;break;
case 1: if(w_c==99) w_c=99; else w_c++;break;
case 2: if(d_c==8) d_c=8; else d_c++;break;
}
} break;
}
}
void Led_control() //led灯控制模块
{
if(rtc_time[0]>=t_c&&(0<(rtc_time[0]-8))) Ucled&=0xfe;
else Ucled|=0x01;
if(wendu>w_c*10) Ucled|=0x02;
else Ucled&=0xfd;
if(g_flag==1&&fg_1==1) {
Ucled&=0xfb;fg_1=0;}
if(g_flag==0&&fg_2==1) {
Ucled|=0x04;fg_2=0;}
Ucled|=0xf8;
if(g_flag==1) {
Ucled&=~(1<<(d_c-1));}
// else Ucled|=~(1<<(d_c-1));
}
void main()
{
System_init();
Timer0Init();
RTC_write(rtc_time);
while(1)
{
Key_process(Key_scan() );
RTC_read(rtc_time);
wendu=rd_temperature();
}
}
void Time0() interrupt 1
{
static uchar i=0;
static uchar j=0;
static uint k1=0;
static uint k2=0;
Data_process();
Smg_display();
Led_control();
if(g_flag==1) if(++k1==3000) {
k1=0; fg_1=1;}
if(g_flag==0) if(++k2==3000) {
k2=0; fg_2=1;}
if(++i==100) {
guang=Pcf_convert();i=0;}
if(++j==10) {
Latch(8,Ucled);j=0;}
}
IIC
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#include "iic.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{
_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
unsigned int Pcf_convert() //光明电阻转化
{
unsigned int light;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x41);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
light=IIC_RecByte()*100/51;
IIC_SendAck(1);
IIC_Stop();
return light;
}
onewire.h
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "reg52.h"
#include "onewire.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
unsigned char j;
while(t--)
{
for(j=10;j>0;j--);}
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
unsigned int rd_temperature(void)
{
unsigned char temp_h,temp_l;
unsigned int temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(10);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
temp_l= Read_DS18B20();
temp_h=Read_DS18B20();
temp=temp_h;
temp<<=8;
temp|=temp_l;
temp=temp*10*0.0625+0.5;
return temp;
}
ds1302.h
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <reg52.h>
#include <intrins.h>
#include "ds1302.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
/*****DS1302时钟芯片部分*****/
void RTC_write(unsigned char *rtc_put)
{
unsigned char temp;
Write_Ds1302_Byte( 0x8e,0x00 );
temp=rtc_put[0]/10*16+rtc_put[0]%10;
Write_Ds1302_Byte( 0x84,temp );
temp=rtc_put[1]/10*16+rtc_put[1]%10;
Write_Ds1302_Byte( 0x82,temp );
temp=rtc_put[2]/10*16+rtc_put[2]%10;
Write_Ds1302_Byte( 0x80,temp );
Write_Ds1302_Byte( 0x8e,0x80 );
}
void RTC_read(unsigned char *rtc_put)
{
unsigned char temp;
temp=Read_Ds1302_Byte( 0x85 );
rtc_put[0]=temp/16*10+temp%16;
temp=Read_Ds1302_Byte( 0x83 );
rtc_put[1]=temp/16*10+temp%16;
temp=Read_Ds1302_Byte( 0x81 );
rtc_put[2]=temp/16*10+temp%16;
}
转载:https://blog.csdn.net/a12345abcdd/article/details/115679447