运用矩阵键盘,将蓝桥杯板子上的大部分模块分别实现,便于练习各个模块的使用。
附带2020官方资源包,在我的资源里可以下载查看。资源链接
***//主函数 ***
#include "common.h"
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
#include "stdio.h"
void init_all();
void delay(uchar t);
extern uchar seg_data[8];//将数码管赋值的数值扩展到main中,可以直接对特定的数码管赋值
uchar code led_show[24] = {
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,
0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,
0x7e,0xbd,0xdb,0xe7,
0xe7,0xdb,0xbd,0x7e};
uchar flag_time = 0;
uchar get_key_value = 0;
uchar seg_count = 0;
uint flag_led = 0;
uchar led_count=0;
uchar key_pre=0;//不将按键归零
//接受温度
uchar wd; //整数
uint wdf;//浮点数
//1302时钟芯片
extern char hour,minute,second;
//ad转换
uchar rd1;//光敏电阻 地址为0x01
uchar rd2;//可调电阻 地址为0x03
//e2prom保存数据的地址,地址自选,或者题目要求具体地址
uchar code e2prom_addr[4] = {
0x10,0x02,0x40,0x50};
//e2prom保存数据
uchar e2prom_data[4] = {
1,2,3,4};
char i=0;
//接受串口数据
char get_uart_data;
//发送串口数据
char send_uart_data[20];
//超声波测距
uint ss=0;
uint s_count=0;//0.5s测一次
void main()
{
init_all();
while(1)
{
if(flag_time>=30)
{
flag_time = 0;
// get_key_value = get_key();//独立按键
get_key_value = get_key_16();//矩阵键盘
if(get_key_value != 0)
key_pre=get_key_value;
switch(key_pre)
{
case 1:{
//读取温度整数
wd = read_wd();
get_seg(11,11,11,11,11,11,wd/10,wd%10);
}break;
case 2:{
//读取温度带小数部分,数码管未添加小数点
wdf = read_wd_f();
get_seg(11,11,11,11,wdf/1000,wdf/100%10,wdf/10%10,wdf%10);
}break;
case 3:{
//1302读取时间
read_time();
get_seg(hour>>4,hour&0x0f,10,minute>>4,minute&0x0f,10,second>>4,second&0x0f);
}break;
case 4:{
//读取rd1光敏电阻
rd1 = read_atod(1);
get_seg(11,11,11,11,11,rd1/100,rd1/10%10,rd1%10);
}break;
case 5:{
//读取rd2电阻
rd2 = read_atod(3);
get_seg(11,11,11,11,11,rd2/100,rd2/10%10,rd2%10);
}break;
case 6:{
if(get_key_value==6)//手动更新e2prom中的数据,避免不断刷新观察不清
{
//读取、写入e2prom数据
e2prom_data[i] = read_data(e2prom_addr[i]);
delay(50);
write_data(e2prom_addr[i],e2prom_data[i]+1);
delay(50);
if(e2prom_data[i]<10)
get_seg(11,11,11,11,11,11,11,e2prom_data[i]);
else
get_seg(11,11,11,11,11,11,e2prom_data[i]/10,e2prom_data[i]%10);
i++;
if(i>=4){
i=0;}
}
}break;
case 7:{
//串口数据接收显示
get_seg(11,11,11,11,11,11,11,get_uart_data);
}break;
case 8:{
//串口向上位机发送数据
if(get_key_value==8)
{
read_time();
//将时间存储到数组中要用int强转才有效加上字符'0'符合ASSIC码格式
send_uart_data[0]=(int)(hour>>4)+'0';
send_uart_data[1]=(int)(hour&0x0f)+'0';
send_uart_data[2]=':';
send_uart_data[3]=(int)(minute>>4)+'0';
send_uart_data[4]=(int)(minute&0x0f)+'0';
send_uart_data[5]=':';
send_uart_data[6]=(int)(second>>4)+'0';
send_uart_data[7]=(int)(second&0x0f)+'0';
send_uart_data[8]='\0';//添加字符结束标志,不添加可能也没错
uart_sendstring(send_uart_data);
uart_sendstring("\r\n");//换行,缩进命令为:\r\t
}
}break;
case 9:{
if(s_count>=400)
{
s_count=0;
send_wave();
TR1=1;
while(P11==1&&TF1==0);
TR1=0;
if(TF1==1)
{
TF1=0;
ss=999;
}
else
{
ss = TH1;
ss = ss<<8;
ss = ss | TL1;
ss = (uint)(ss * 0.017); TH1=0;TL0=0;
}
get_seg(11,11,11,11,11,ss/100,ss/10%10,ss%10);
}
};break;
case 10:seg_data[0]=1;seg_data[1]=0;break;
case 11:seg_data[0]=1;seg_data[1]=1;break;
case 12:seg_data[0]=1;seg_data[1]=2;break;
case 13:seg_data[0]=1;seg_data[1]=3;break;
case 14:seg_data[0]=1;seg_data[1]=4;break;
case 15:seg_data[0]=1;seg_data[1]=5;break;
case 16:seg_data[0]=1;seg_data[1]=6;break;
}
}
}
}
void init_all()
{
// char i;
Y(4);P0=0xff;
Y(5);P0=0x00;
Y(0);
init_timer();//初始化定时器
// Timer1Init();//UartInit();
write_time(0x10,0x46,0x55);//写入1302时间
//uart_sendstring("hello world\0");
read_wd();delay(50); //读取一次18b20的温度值防止后面读取温度不准确
// for(i=0;i<4;i++)
// { //写入e2prom中的数据
// write_data(e2prom_addr[i],e2prom_data[i]);
// delay(50);//给个延时,给它时间让它写进去
// delay(50);//给个延时,给它时间让它写进去
// }
}
void timer0() interrupt 1
{
flag_time++;
flag_led++;
if(key_pre==9)
s_count++;
if(flag_led>=500)
{
flag_led=0;
Y(4);P0=led_show[led_count];Y(0);
led_count++;
if(led_count>=24)
led_count=0;
}
show_seg(seg_count);
seg_count++;
if(seg_count>=8){
seg_count=0;}
}
void uart0() interrupt 4
{
if(RI==1)
{
RI=0;
get_uart_data = SBUF;
}
}
void delay(uchar t)
{
uchar i,j;
for(i=0;i<t;i++)
for(j=0;j<110;j++);
}
***//common模块 ***
common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include "STC15F2K60S2.H"
#define uchar unsigned char
#define uint unsigned int
sbit TS = P1^0;
sbit RS = P1^1;
void Y(uchar channel);
void get_seg(uchar d1,d2,d3,d4,d5,d6,d7,d8);
void show_seg(uchar count);
void init_timer();
void Timer1Init(void); //0微秒@12.000MHz
void send_wave();//超声波
void UartInit(void);
void uart_sendstring(char *str);
uchar get_key();
uchar get_key_16();
#endif
common.c
#include "common.h"
#include "intrins.h"
#define somenop _nop_()
// ;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
uchar code wela[8] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar code dula[12] = {
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
uchar seg_data[8] = {
11,11,11,11,11,11,11,11};
uchar flag_key_count = 0;
uchar key_value = 0;
bit flag_key_down = 0;
void Y(uchar channel)
{
switch(channel)
{
case 4: P2 = (P2 & 0x1f) | 0x80;break;
case 5: P2 = (P2 & 0x1f) | 0xa0;break;
case 6: P2 = (P2 & 0x1f) | 0xc0;break;
case 7: P2 = (P2 & 0x1f) | 0xe0;break;
case 0: P2 = (P2 & 0x1f) | 0x00;break;
}
}
void get_seg(uchar d1,d2,d3,d4,d5,d6,d7,d8)
{
if(d1<12) seg_data[0] = d1;
if(d2<12) seg_data[1] = d2;
if(d3<12) seg_data[2] = d3;
if(d4<12) seg_data[3] = d4;
if(d5<12) seg_data[4] = d5;
if(d6<12) seg_data[5] = d6;
if(d7<12) seg_data[6] = d7;
if(d8<12) seg_data[7] = d8;
}
void show_seg(uchar count)
{
Y(6);P0 = wela[count];
Y(7);P0 = dula[seg_data[count]];
Y(0);
}
void init_timer()
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TMOD |= 0x10; //设置定时器模式
TL1 = 0x00; //设置定时初值
TH1 = 0x00; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 0; //定时器1开始计时
EA = 1;
ET0 = 1;
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //0微秒@12.000MHz
{
// AUXR &= 0xBF; //定时器时钟12T模式
// TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x00; //设置定时初值
TH1 = 0x00; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 0; //定时器1开始计时
}
void send_wave()
{
char i=0;
while(i<8)
{
i++;
P10=1;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
P10=0;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
}
}
void UartInit(void) //[email protected]
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0x1E; //设定定时初值
TH1 = 0xFB; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES = 1;
}
//void uart_sendstring(char *str)
//{
// char *s;
// s = str;
// ES = 0;
// while(*s!='\0')
// {
// SBUF=*s;
// while(TI==0);
// TI s++;=0;
//
// }
// ES = 1;
//}
uchar get_key()
{
if((P3&0x0f)!=0x0f)
{
flag_key_count++;}
else
{
flag_key_count=0;}
if(flag_key_count>=5)
{
flag_key_count = 0;
flag_key_down = 1;
if(P33==0)
{
key_value=4;
}
else if(P32==0)
{
key_value=5;
}
else if(P31==0)
{
key_value=6;
}
else if(P30==0)
{
key_value=7;
}
}
if(flag_key_down==1 && ((P3&0x0f)==0x0f))
{
flag_key_down=0;
return key_value;
}
return 0;
}
uchar get_key_16()
{
P3=0x0f;P44=0;P42=0;//p36、p37在矩阵键盘中用p42、p44替代
if((P3&0x0f)!=0x0f)
{
flag_key_count++;
}
else
{
flag_key_count=0;
}
if(flag_key_count>=5)
{
flag_key_count=0;
flag_key_down=1;
P3=0x0f;P44=0;P42=0;//行扫描
if(P30==0) {
key_value=0;}
else if(P31==0){
key_value=4;}
else if(P32==0){
key_value=8;}
else if(P33==0){
key_value=12;}
P3=0xf0;P44=1;P42=1;//列扫描
if(P44==0){
key_value=key_value+1;}
else if(P42==0){
key_value=key_value+2;}
else if(P35==0){
key_value=key_value+3;}
else if(P34==0){
key_value=key_value+4;}
}
//松开按键才赋值有效
P3=0x0f;P44=0;P42=0;
if(flag_key_down==1 && ((P3&0x0f)==0x0f))
{
flag_key_down=0;
return key_value;
}
return 0;
}
char key()
{
P3=0x0f;P44=0;P42=0;
if((P3&0x0f)!=0x0f)
flag_key_count++;
else
flag_key_count=0;
if(flag_key_count>=5)
{
flag_key_count=0;
flag_key_down=1;
P3=0x0f;P44=0;P42=0;
if(P30==0) key_value=0;
else if(P31==0) key_value=4;
else if(P32==0) key_value=8;
else if(P33==0) key_value=12;
P3=0xf0;P44=1;P42=1;
if(P44==0) key_value = key_value+1;
else if(P42==0) key_value = key_value+2;
else if(P35==0) key_value = key_value+3;
else if(P34==0) key_value = key_value+4;
}
P3=0x0f;P44=0;P42=0;
if(flag_key_down==1 && ((P3&0x0f)==0x0f))
{
flag_key_down=0;
return key_value;
}
return 0;
}
**//ds1302模块 **
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
//void Write_Ds1302(unsigned char temp);
//void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
//unsigned char Read_Ds1302_Byte( unsigned char address );
void read_time();
void write_time(char h,m,s);
#endif
ds1302.c
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include
#include
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
char hour;
char minute;
char second;
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);
}
void read_time()
{
second = Read_Ds1302_Byte(0x81);
minute = Read_Ds1302_Byte(0x83);
hour = Read_Ds1302_Byte(0x85);
}
void write_time(char h,m,s)
{
Write_Ds1302_Byte(0x80,s);
Write_Ds1302_Byte(0x82,m);
Write_Ds1302_Byte(0x84,h);
}
***//onewire模块 ***
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
//unsigned char rd_temperature(void); //; ;
unsigned char read_wd();
unsigned int read_wd_f();
#endif
onewire.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t = t * 12;
while(t--);
}
//通过单总线向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 char read_wd()
{
unsigned char low,high,temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(1000);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
high = high << 4;
temp = high | (low>>4);
return temp;
}
unsigned int read_wd_f()
{
unsigned int low,high;
unsigned int temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(1000);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
high = (high&0x0f) << 8;
temp = high | low;
temp = (temp * 0.0625)*100;
return temp;
}
//iic模块
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.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;
}
void write_data(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_data(unsigned char addr)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(0);
IIC_Stop();
return temp;
}
unsigned char read_atod(unsigned char addr)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(0);
IIC_Stop();
return temp;
}