目录
题目
链接:https://pan.baidu.com/s/1YNoXIue8yaNIr1EJAL6N-g
提取码:tucz
考点
1、LED,矩阵按键,数码管
2、DAC,EEPROM
3、超声波测距
4、串口
5、测温
代码
主函数
#include <stc15f2k60s2.h>
#include "intrins.h"
#include "onewire.h"
#include "iic.h"
#include <stdio.h>
# include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define semopon {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit Buzzer = P0^6;
sbit Relay = P0^4;
sbit TX = P1^0;
sbit RX = P1^1;
/************* 本地常量声明 **************/
uchar code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
uchar code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
uchar table[]={16,16,16,16,16,16,16,16};
//按键
uchar ReadData,Trg,Cont,Keypress;
//长按与短按同时使用时
uchar key_up,key_12,key_13;
bit key_flag;
//指示灯
uchar LED;
//超声波
uint t,ucDist,Dist;//时间,距离
int dist_temp=35;//距离参数
bit dist_flag;
//功能
bit mode_falg=1;//0为数据界面,1为参数设置界面
uchar set_mode=0,set_mode_num=0;//set_mode为数据界面切换,set_mode_num为参数界面切换
float temp;//温度
int temp_num=30;//温度参数
uint num=0;//变更次数
bit temp_flag;
bit DAC_flag;//dac输出状态 0:启动 1:停止
uint cun[4]={30,35,30,35};//变量转换,保存有效值的
//串口
bit busy;
uchar rx_buf[30];
uchar rx_cnt=0;
bit rx_flag;
uchar rx_ideltime=0;//计时的
void vRxIdle_press();
//关闭外设
void allinit()
{
P2=0xa0;Buzzer = 0;Relay = 0; P2=0x00;
P2=0x80;P0=0xff;P2=0x00;
}
//指示灯
void Set_LED()
{
P2=0x80;P0=~LED;P2=0x00;
}
void Timer5Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //允许中断 //定时器2必须写
}
void Timer() interrupt 12
{
static uint smg_count,key_count,i,temp_count,dist_count;
static int p=0,q=0;
if(++smg_count>=2)
{
smg_count=0;
P2=0xe0;P0=0xff;P2=0x00;
P2=0xc0;P0=T_COM[i];P2=0x00;
P2=0xe0;P0=~t_display[table[i]];P2=0x00;
i++;
if(i>=8)i=0;
}
if(++key_count>=10)//按键消抖
{
key_count=0;
key_flag=1;
}
if(++temp_count>=200)//温度读取
{
temp_count=0;
temp_flag=1;
}
if(++dist_count>=200)//距离读取
{
dist_count=0;
dist_flag=1;
}
if(key_12&&!key_up)//s12长按
{
if(++p>=1000)
{
num=0;
key_12=0;
p=0;
}
}else{
p=0;
}
if(key_13&&!key_up)//s13长按
{
if(++q>=1000)
{
DAC_flag=~DAC_flag;//dac停止
key_13=0;
q=0;
}
}else{
q=0;
}
vRxIdle_press();//串口清除函数
}
//矩阵按键
void ReadKey()
{
P3=0xf0;
P44=P42=1;
P37=P44;
P36=P42;
Keypress=P3;
P3=0x0f;
P44=P42=0;
ReadData=(P3|Keypress)^0xff;
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
}
void disp_key()
{
if(key_flag)
{
key_flag=0;
Set_LED();
ReadKey();
if(Cont==0)key_up=1;
if(Trg==0x28)//s12
{
key_up=0;
key_12=1;
}
if(Trg==0x24)//s13
{
key_up=0;
key_13=1;
}
if(key_12&&key_up)//s12短按
{
EA=0;
Write_eeprom(0x18,num);
EA=1;
if(mode_falg==0){
set_mode++;
if(set_mode>=3)set_mode=0;
}
if(mode_falg==1)
{
set_mode_num++;
if(set_mode_num>=2)set_mode_num=0;
}
key_12=0;
}
if(key_13&&key_up)//s13短按
{
mode_falg=~mode_falg;
if(mode_falg==0)set_mode=0;
if(mode_falg==1)set_mode_num=0;
key_13=0;
}
if(Trg==0x18)//s16
{
if(mode_falg&&set_mode_num==0)
{
temp_num-=2;
if(temp_num<0)temp_num=0;
}
if(mode_falg&&set_mode_num==1)
{
dist_temp-=5;
if(dist_temp<0)dist_temp=0;
}
}
if(Trg==0x14)//s17
{
if(mode_falg&&set_mode_num==0)
{
temp_num+=2;
if(temp_num>98)temp_num=98;
}
if(mode_falg&&set_mode_num==1)
{
dist_temp+=5;
if(dist_temp>95)dist_temp=95;
}
}
}
}
//超声波
void Send_wavc()
{
uchar i=8;
do{
TX=1;
semopon;semopon;semopon;semopon;semopon;semopon;
semopon;semopon;
TX=0;
semopon;semopon;semopon;semopon;semopon;semopon;
semopon;semopon;
}while(i--);
}
uint Read_DIST()
{
if(dist_flag)
{
dist_flag=0;
Send_wavc();
TR0=1;
while((RX==1)&&(TF0==0));
TR0=0;
if(TF0==1)
{
TF0=0;
ucDist=49;//范围是10-50
}else{
t=TH0;
t<<=8;
t|=TL0;
ucDist=(int)(t*0.017);
}
TH0=0;
TL0=0;
}
return ucDist;
}
void disp_DAC()
{
if(DAC_flag==0)//启动
{
if(Dist<=dist_temp)
{
Write_dac(102);//2v
}else{
Write_dac(204);//4v
}
}else{//停止
Write_dac(20);//0.4v
}
}
void disp_LED()
{
if((temp/100)>=temp_num)
{
LED|=1;//L1亮
}else{
LED&=~1;//L1灭
}
if(Dist>=dist_temp)
{
LED|=2;//L2亮
}else{
LED&=~2;//L2灭
}
if(DAC_flag==0)
{
LED|=4;//L3亮
}else{
LED&=~4;//L3灭
}
LED&=~0xf8;
}
串口
void UartInit(void) //4800bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0x8F; //设定定时初值
TH1 = 0xFD; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES=1;
EA=1;
}
//串口服务函数
void isr_uart() interrupt 4
{
if(RI)
{
RI=0;
rx_ideltime=0;
rx_buf[rx_cnt++]=SBUF;
if(rx_buf[rx_cnt-1] == '\n')
{
rx_cnt=0;
rx_flag=1;
}
}
if(TI)
{
TI=0;
busy=0;
}
}
//串口接收空闲时间计时
void vRxIdle_press()
{
rx_ideltime++;
if(rx_ideltime>=50)
{
rx_ideltime=0;
rx_cnt=0;
memset(rx_buf,'\0',sizeof(rx_buf));
}
}
//串口发送数据
void SendData(uchar dat)
{
while(busy);
busy=1;
SBUF=dat;
}
//发送字符串
void SendString(char *s)
{
while(*s)
{
SendData(*s++);
}
}
//串口发送和接收
void vUartRX_press()
{
if(rx_flag)
{
rx_flag=0;
if(rx_buf[0]=='S' && rx_buf[1]=='T' && rx_buf[2]=='\r')
{
SendData('$');SendData(Dist/10+'0');SendData(Dist%10+'0');SendData(',');
SendData((int)temp/1000+'0');SendData((int)temp/100%10+'0');SendData('.');
SendData((int)temp/10%10+'0');SendData((int)temp%10+'0');
SendString("\r\n");
}
else if(rx_buf[0]=='P' && rx_buf[1]=='A' && rx_buf[2]=='R' && rx_buf[3]=='A' && rx_buf[4]=='\r')
{
SendData('#');SendData(temp_num/10+'0');SendData(temp_num%10+'0');SendData(',');
SendData(dist_temp/10+'0');SendData(dist_temp%10+'0');
SendString("\r\n");
}
else
{
SendString("ERROR\r\n");
}
}
}
//主函数
void main()
{
allinit();
UartInit();
Timer5Init();
num=Read_eeprom(0x18);
while((int)(Read_Temp()*0.0625)==85);
while(1)
{
if(temp_flag)
{
temp_flag=0;
//EA=0;
temp=Read_Temp()*0.0625*100;
//EA=1;
}
Dist=Read_DIST();
if(mode_falg==0)
{
cun[2]=temp_num;
cun[3]=dist_temp;
if(cun[0]!=cun[2]||cun[1]!=cun[3])
{
num++;
if(num>=65536)num=65536;
cun[0]=cun[2];
cun[1]=cun[3];
}
}
if(mode_falg==0)//数据界面
{
switch(set_mode)
{
case 0://温度
table[0]=12;table[1]=16;
table[2]=16;table[3]=16;
table[4]=(int)temp/1000;table[5]=(int)temp/100%10+32;
table[6]=(int)temp/10%10;table[7]=(int)temp%10;
break;
case 1://距离
table[0]=21;table[1]=16;
table[2]=16;table[3]=16;
table[4]=16;table[5]=16;
table[6]=Dist/10;table[7]=Dist%10;
break;
case 2://变更次数
table[0]=28;table[1]=16;
table[2]=16;
table[3]=(num>=10000)?num/10000:16;
table[4]=(num>=1000)?num/1000%10:16;
table[5]=(num>=100)?num/100%10:16;
table[6]=(num>=10)?num/10%10:16;
table[7]=num%10;
break;
}
}
else{//参数设置界面
switch(set_mode_num)
{
case 0://温度
table[0]=24;table[1]=16;
table[2]=16;table[3]=1;
table[4]=16;table[5]=16;
table[6]=temp_num/10;table[7]=temp_num%10;
break;
case 1://距离
table[0]=24;table[1]=16;
table[2]=16;table[3]=2;
table[4]=16;table[5]=16;
table[6]=dist_temp/10;table[7]=dist_temp%10;
break;
}
}
vUartRX_press();//串口
disp_LED();//灯
disp_DAC();//dac
disp_key();//按键
}
}
iic
1、iic.c
/*
程序说明: 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);
}
//等待应答
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;
}
//eeprom
void Write_eeprom(unsigned char add,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read_eeprom(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return temp;
}
//DAC
void Write_dac(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
2、iic.h
#ifndef _IIC_H
#define _IIC_H
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
//eeprom
void Write_eeprom(unsigned char add,unsigned char dat);
unsigned char Read_eeprom(unsigned char add);
//DAC
void Write_dac(unsigned char dat);
#endif
onewire
1、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*10;
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;
}
//读取温度
int Read_Temp()
{
unsigned char low,high;
int temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(high<<8|low);
return temp;
}
2、onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
unsigned char rd_temperature(void); //
//读取温度
int Read_Temp();
#endif
总结
串口恶心得一批,不过以后遇到应该能解决了!!!