(萌新一枚。连肝4个小时,在这里分享给大家。)
这一届的题目总体来说,难度不大。但第一次也是唯一一次考到了矩阵键盘,足以引起我们的注意。我在写代码的过程,主要遇到的障碍就是矩阵键盘的使用过于粗糙。希望矩阵键盘没有怎么练习过的,只会运用最基础的操作的小伙伴能进一步加强这一块的学习,防止比赛暴雷。。。。
如果你发现了程序需要优化的地方,请一定要告诉我!
onewire.c
#include "reg52.h"
#include "onewire.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t *= 10;//时间扩大十倍
while(t--);
}
//通过单总线xiangDS18B20写一个字节
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;
}
uchar read_temperatuer(void)
{
uchar LSB, MSB;
uchar temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(100);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
temp = (MSB << 8)|LSB;
temp >>= 4;//右移4位,只取整数部分
return temp;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#define uchar unsigned char
#define uint unsigned int
extern uchar read_temperatuer(void);
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
main.c
#include <REGX52.H>
#include <onewire.h>
sfr P4 = 0xc0;
sbit P42 = P4^2;
sbit P44 = P4^4;
sbit L1 = P0^0;
sbit L2 = P0^1;
void Delay(uint t);
void Init_hc573(uint s);
void key_scan(void);
void inputdat(uint key);//输入数据
void save_t(void);//保存输入的数据
void Init_Timer0(void);
void DisplaySMG_Dat(uint pos, uint dat);
void DisplaySMG_all(void);//清空所有数码管
void DisplaySMG(void);
uint code Shu[] =
{ 0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,0x80,0x90,//0-9
0xbf, 0xff};//-和灭
uint yi=11,er=11,san=11,si=11, wu=11, liu=11, qi=11, ba=11;
uint temperature;//温度
uint set;//控制显示界面标志位
uint set_t1, set_t2, set_t3, set_t4;//设置温度的临时数据
uint Tmax = 30, Tmin = 20;
uint level;//温度等级
uint sel;//选择要修改的数据
uint flag;//计算设置按键按下的次数
uint clear;//清空数据标志位
uint count_0;//定时器时间控制
uint count_1;
uint count_2;
void main(){
Init_hc573(4);
P0 = 0xff;
Init_hc573(5);
P0 = 0x00;
Init_Timer0();
while(1){
key_scan();
if(temperature < Tmin){
level = 0;
Init_hc573(5);
P0 = 0x00;
}
else if((temperature >= Tmin)&&(temperature <= Tmax)){
level = 1;
Init_hc573(5);
P0 = 0x00;
}
else
{
level = 2;
Init_hc573(5);
P0 = 0x10;
}
if(set== 0){
EA = 1;
ET0 = 1;
temperature = read_temperatuer();
yi = 10;er = level;san = 10;
si = 11;wu = 11;liu = 11;
qi = temperature/10;ba = temperature%10;
}
else{
//关闭定时器并清空数据
EA = 0;
ET0 = 0;
count_0 = 0;
count_1 = 0;
count_2 = 0;
yi = 10;er = set_t1;san = set_t2;
si = 11;wu = 11;liu = 10;
qi = set_t3;ba = set_t4;
}
DisplaySMG();
}
}
void Delay(uint t){
while(t --);
}
void Init_hc573(uint s){
switch(s){
case 4:P2 = (P2 &0x1f)|0x80;break;//LED
case 5:P2 = (P2 &0x1f)|0xa0;break;//蜂鸣器和继电器
case 6:P2 = (P2 &0x1f)|0xc0;break;//数码管com端口
case 7:P2 = (P2 &0x1f)|0xe0;break;//段码
}
}
static uint key;
void key_scan(void){
uint temp;
P3 = 0x7f;P42 = 1;P44 = 0;//扫描第一列
temp = P3;
temp &= 0x0f;//判断第四位是否发生变化 0111 1111&0000 1111 = 0000 1111
if(temp != 0x0f){
Delay(200);
if(temp != 0x0f){
temp = P3;
switch(temp)//便于直接控制到每个按键
{
case 0x7e:if(set == 1){ sel ++;key = 0;inputdat();}break;
case 0x7d:if(set == 1){ sel ++;key = 3;inputdat();}break;
case 0x7b:if(set == 1){ sel ++;key = 6;inputdat();}break;
case 0x77:if(set == 1){ sel ++;key = 9;inputdat();}break;
}
while(temp != 0x0f){ //重新判断,否则temp永远不能等于0x0f
temp = P3;
temp &= 0x0f;//若松开,则temp = 0x0f;
}
}
}
P3 = 0xbf;P42 = 0;P44 = 1;//判断第二列
temp = P3;
temp &= 0x0f;//判断第四位是否发生变化
if(temp != 0x0f){
Delay(200);
if(temp != 0x0f){
temp = P3;
switch(temp)
{
case 0xbe:if(set == 1){ sel ++;key = 1;inputdat();}break;
case 0xbd:if(set == 1){ sel ++;key = 4;inputdat();}break;
case 0xbb:if(set == 1){ sel ++;key = 7;inputdat();}break;
case 0xb7:set = 1;flag ++;if(flag == 2){ save_t();}break;
}
while(temp != 0x0f){
temp = P3;
temp &= 0x0f;
}
}
}
P3 = 0xdf;P42 = 1;P44 = 1;//扫描第三列
temp = P3;
temp &= 0x0f;
if(temp != 0x0f){
Delay(200);
if(temp != 0x0f){
temp = P3;
switch(temp)
{
case 0xde:if(set == 1){ sel ++;key = 2;inputdat();}break;
case 0xdd:if(set == 1){ sel ++;key = 5;inputdat();}break;
case 0xdb:if(set == 1){ sel ++;key = 8;inputdat();}break;
case 0xd7:if(set == 1){ sel ++;clear = 1;inputdat();}break;
}
while(temp != 0x0f){
temp = P3;
temp &= 0x0f;
}
}
}
}
void inputdat(void){
if(clear == 0){
switch(sel){
case 1:set_t1 = key;break;
case 2:set_t2 = key;break;
case 3:set_t3 = key;break;
case 4:set_t4 = key;break;
}
}
else{ //清空数据
set_t1 = 0;
set_t2 = 0;
set_t3 = 0;
set_t4 = 0;
sel = 0;//重新输入
clear = 0;
}
}
void save_t(void){
if((set_t1*10+ set_t2) > (set_t3*10+ set_t4)){
Tmin = set_t3*10+ set_t4;
Tmax = set_t1*10+ set_t2;
sel = 0;
set = 0;
Init_hc573(4);
L2 = 1;
}
else{ //输入错误,重新输入
set_t1 = 0;
set_t2 = 0;
set_t3 = 0;
set_t4 = 0;
sel = 0;
set = 1;
Init_hc573(4);
L2 = 0;
}
flag = 0;//清空设置按键标志位
}
void Init_Timer0(void){ //@12MHz
TMOD = 0x01;
TH0 = (65535 -20000)/256;
TL0 = (65535- 20000)%256;
// EA = 1;
// ET0 = 1;
TR0 = 1;
}
void service_Timer0(void) interrupt 1{
TH0 = (65535 -20000)/256;
TL0 = (65535- 20000)%256;
count_0 ++;
count_1 ++;
count_2 ++;
if(count_0 == 4){
count_0 = 0;
if(level == 0){
if(L1 == 0){
Init_hc573(4);
P0 = 0xff;//避免其他LED闪烁
L1 = 1;
}
else
{
Init_hc573(4);
P0 = 0xff;
L1 = 0;
}
}
}
if(count_1 == 2){
count_1 = 0;
if(level == 1){
if(L1 == 0){
Init_hc573(4);
P0 = 0xff;
L1 = 1;
}
else{
Init_hc573(4);
P0 = 0xff;
L1 = 0;
}
}
}
if(count_2 == 1){
count_2 = 0;
if(level == 2){
if(L1 == 0){
Init_hc573(4);
P0 = 0xff;
L1 = 1;
}
else{
Init_hc573(4);
P0 = 0xff;
L1 = 0;
}
}
}
}
void DisplaySMG_Dat(uint pos, uint dat){
Init_hc573(6);
P0 = 0x01 << pos;
Init_hc573(7);
P0 = dat;
Delay(50);
P0 = 0xff;
}
void DisplaySMG_all(void){
Init_hc573(6);
P0 = 0xff;
Init_hc573(7);
P0 = 0xff;
}
void DisplaySMG(void){
DisplaySMG_Dat(0, Shu[yi]);
Delay(100);
DisplaySMG_Dat(1, Shu[er]);
Delay(100);
DisplaySMG_Dat(2, Shu[san]);
Delay(100);
DisplaySMG_Dat(3, Shu[si]);
Delay(100);
DisplaySMG_Dat(4, Shu[wu]);
Delay(100);
DisplaySMG_Dat(5, Shu[liu]);
Delay(100);
DisplaySMG_Dat(6, Shu[qi]);
Delay(100);
DisplaySMG_Dat(7, Shu[ba]);
Delay(100);
DisplaySMG_all();
}
end