本次测试包含基本底层——在不冲突的条件下,其包含了数码管, led,按键, DS13B20,DS1302,EEMPRO,串口的使用,等明天会更新其他的NE555(5位)以及超声波的使用
hc573.c
#include <STC15F2K60S2.H>
void SelectHC573(unsigned char n)
{
switch(n)
{
case 4:
P2 = (P2&0x1f)|0x80;
P2 &= 0x1f;
break;
case 5:
P2 = (P2&0x1f)|0xa0;
P2 &= 0x1f;
break;
case 6:
P2 = (P2&0x1f)|0xc0;
P2 &= 0x1f;
break;
case 7:
P2 = (P2&0x1f)|0xe0;
P2 &= 0x1f;
break;
}
}
led.c
#include <STC15F2K60S2.H>
#include "hc573.h"
void Led_Disp(unsigned char addr,enable)
{
static unsigned char temp = 0x00;
static unsigned char temp_old = 0xff;
if(enable)
temp |= 0x01<<addr;
else
temp &= ~(0x01<<addr);
if(temp != temp_old)
{
P0 = ~temp;
SelectHC573(4);
temp_old = temp;
}
}
void Beep(unsigned char flag)
{
static unsigned char temp = 0x00;
static unsigned char temp_old = 0xff;
if(flag)
temp |= 0x40;
else
temp &= ~0x40;
if(temp != temp_old)
{
P0 = temp;
SelectHC573(5);
temp_old = temp;
}
}
void Relay(unsigned char flag)
{
static unsigned char temp = 0x00;
static unsigned char temp_old = 0xff;
if(flag)
temp |= 0x40;
else
temp &= ~0x40;
if(temp != temp_old)
{
P0 = temp;
SelectHC573(5);
temp_old = temp;
}
}
key.c
#include <STC15F2K60S2.H>
#include "hc573.h"
unsigned char Key_Read()
{
unsigned char temp=0;
P44=0;P42=1;P35=1;P34=1;
if(P33==0) temp=4;
if(P32==0) temp=5;
if(P31==0) temp=6;
if(P30==0) temp=7;
P44=1;P42=0;P35=1;P34=1;
if(P33==0) temp=8;
if(P32==0) temp=9;
if(P31==0) temp=10;
if(P30==0) temp=11;
P44=1;P42=1;P35=0;P34=1;
if(P33==0) temp=12;
if(P32==0) temp=13;
if(P31==0) temp=14;
if(P30==0) temp=15;
P44=1;P42=1;P35=1;P34=0;
if(P33==0) temp=16;
if(P32==0) temp=17;
if(P31==0) temp=18;
if(P30==0) temp=19;
return temp;
}
seg.h
#include <STC15F2K60S2.H>
#include "hc573.h"
unsigned char code seg_dula[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0xff,
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e //F
};
unsigned char code seg_wela[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void Seg_Disp(unsigned char wela,dula,point)
{
P0 = 0xff;
SelectHC573(7);
P0 = seg_wela[wela];
SelectHC573(6);
P0 = seg_dula[dula];
if(point)
P0 &= 0x7f;
SelectHC573(7);
}
init.c 初始化函数
#include <STC15F2K60S2.H>
#include "hc573.h"
void Init()
{
P0 = 0xff;
SelectHC573(4);
P0 = 0x00;
SelectHC573(5);
}
onewire.c 温度传感器
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
/* 温度模块 */
#include "reg52.h"
#include "intrins.h"
sbit DQ = P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
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);
}
//
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;
}
//
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;
}
float rd_temp()
{
unsigned char high,low;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
// 先转化,再读取,看顺序,手册
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
return ((high<<8)|low)/16.0;
}
iic.c 包含EEMPROM 与 DAC与ADC
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "reg52.h"
#include "intrins.h"
sbit scl = P2^0;
sbit sda = P2^1;
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
unsigned char Ad_Read(unsigned char addr)
{
unsigned char dat;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return dat;
}
void Da_Write(unsigned char temp)
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(temp);
I2CWaitAck();
I2CStop();
}
void EMMPROM_Write(unsigned char *string,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
while(num--)
{
I2CSendByte(*string++);
I2CWaitAck();
I2C_Delay(200);
}
I2CStop();
}
void EMMPROM_Read(unsigned char *string,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(num--)
{
*string++ = I2CReceiveByte();
if(num) I2CSendAck(0);
else I2CSendAck(1);
}
I2CStop();
}
ds1302.c 时钟函数
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "reg52.h"
#include "intrins.h"
sbit SCK = P1^7;
sbit RST = P1^3;
sbit SDA = P2^3;
unsigned char Write_addr[]={0x84,0x82,0x80};
unsigned char Read_addr[]={0x85,0x83,0x81};
//
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 Set_Rtc(unsigned char *ucRtc)
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<3;i++)
{
Write_Ds1302_Byte(Write_addr[i],ucRtc[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void Read_Rtc(unsigned char *ucRtc)
{
unsigned char i;
for(i=0;i<3;i++)
ucRtc[i] = Read_Ds1302_Byte(Read_addr[i]);
}
uart.c 串口函数——发送与初始化 服务函数放在主函数
#include <STC15F2K60S2.H>
#include "intrins.h"
void UartInit(void) //9600bps@12.000MHz,³õʼ»¯º¯Êý
{
SCON = 0x50;
AUXR |= 0x01;
AUXR |= 0x04;
T2L = 0xC7;
T2H = 0xFE;
AUXR |= 0x10;
EA = 1;
ES = 1;
}
void Send_Byte(unsigned char dat)
{
SBUF = dat;
while(TI == 0); //²»ÊÇ0¾ÍÍ˳ö
TI = 0;
}
void Send_String(unsigned char *dat)
{
while(*dat != '\0')
Send_Byte(*dat++);
}
超声波,我们使用的是T1定时器,其中TH为高位TL为低位,TR为计数器,TF为溢出
wave.c
#include "reg52.h"
#include "intrins.h"
sbit Tx = P1^0;
sbit Rx = P1^1;
void Delay13us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 36;
while (--i);
}
void Wave_Init()
{
Tx = 1;
Delay13us();
Tx = 0;
Delay13us();
}
unsigned int Rd_distance()
{
unsigned int time=0;
TMOD &= 0x0f;
TH1 = TL1 = 0;
Wave_Init();
TR1 = 1; //¿ªÊ¼¼Æʱ
while((Rx == 1)&&(TF1 == 0));
TR1 = 0;
if(TF1 == 0)
{
time = (TH1<<8)|TL1;
return (time*0.017);
}
else
{
TF1=0;
return 0;
}
}
最后则是他们的使用 main.c
#include <STC15F2K60S2.H>
#include "led.h"
#include "init.h"
#include "seg.h"
#include "key.h"
#include "onewire.h"
#include "iic.h"
#include "ds1302.h"
#include "uart.h"
#include "wave.h"
#include <stdio.h>
/* ÉùÃ÷ÇøÓò */
unsigned char Key_val,Key_old,Key_down;
unsigned char Key_Slow_Down;
unsigned char Seg_Buf[]={10,10,10,10,10,10,10,10};
unsigned char Seg_Point[]={0,0,0,0,0,0,0,0};
unsigned char Seg_Pos;
unsigned int Seg_Slow_Down;
unsigned char ucLed[]={0,0,0,0,0,0,0,0};
unsigned char ucRtc[3] = {0x08,0x30,0x00};
unsigned char ucRtc_Index=0;
unsigned char Uart_Buf[12];
unsigned char Uart_num=0;
float temp;
float V_dat;
unsigned char V_Disp=35;
unsigned int distance;
unsigned char Seg_Mode;
/* °´¼üº¯Êý */
void Key_Proc()
{
if(Key_Slow_Down) return;
Key_Slow_Down = 1;
Key_val = Key_Read();
Key_down = Key_val&(Key_old^Key_val);
Key_old = Key_val;
switch(Key_down)
{
case 4:
if(++Seg_Mode==5)
Seg_Mode = 0;
break;
case 5:
if(Seg_Mode==2)
{
V_Disp = V_Disp+5;
if(V_Disp==95)
V_Disp=0;
}
break;
case 6:
if(Seg_Mode==2)
{
V_Disp = V_Disp-5;
if(V_Disp==0)
V_Disp=95;
}
break;
case 7:
EMMPROM_Write(&V_Disp,0,1);
break;
case 8:
sprintf(Uart_Buf,"V=%.2fV \r\n",V_dat);
Send_String(Uart_Buf);
break;
}
}
/* ÊýÂë¹Üº¯Êý */
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;
/* Êý¾Ý¶ÁÈ¡ÇøÓò */
temp = rd_temp();
V_dat = Ad_Read(0x03)/51.0;
Read_Rtc(ucRtc); //¶Áȡʱ¼ä
distance = Rd_distance();
/* Êý¾ÝÏÔʾÇøÓò */
switch(Seg_Mode)
{
case 0:
Seg_Buf[0]=10;
Seg_Buf[1]=10;
Seg_Buf[3]=10;
Seg_Buf[4]=10;
Seg_Buf[5]=(unsigned char)temp/10;
Seg_Buf[6]=(unsigned char)temp%10;
Seg_Buf[7]=(unsigned char)(temp*10) % 10;
Seg_Point[6]=1;
break;
case 1:
Seg_Buf[0]=10;
Seg_Buf[1]=10;
Seg_Buf[3]=10;
Seg_Buf[4]=10;
Seg_Buf[5]=(unsigned char)V_dat; // 0~5
Seg_Buf[6]=(unsigned char)(V_dat*10)%10;
Seg_Buf[7]=(unsigned char)(V_dat*100)%10;
Seg_Point[6]=0;
Seg_Point[5]=1;
break;
case 2:
Seg_Buf[0]=10;
Seg_Buf[1]=10;
Seg_Buf[3]=10;
Seg_Buf[4]=10;
Seg_Buf[5]=0;
Seg_Buf[6]=V_Disp/10;
Seg_Buf[7]=V_Disp%10;
Seg_Point[6]=0;
Seg_Point[5]=0;
break;
case 3:
Seg_Buf[0]=ucRtc[0]/16;
Seg_Buf[1]=ucRtc[0]%16;
Seg_Buf[3]=ucRtc[1]/16;
Seg_Buf[4]=ucRtc[1]%16;
Seg_Buf[5]=10;
Seg_Buf[6]=ucRtc[2]/16;
Seg_Buf[7]=ucRtc[2]%16;
break;
case 4:
Seg_Buf[0]=10;
Seg_Buf[1]=10;
Seg_Buf[3]=10;
Seg_Buf[4]=10;
Seg_Buf[5]=distance/100;
Seg_Buf[6]=distance/10%10;
Seg_Buf[7]=distance%10;
break;
}
}
void Led_Proc()
{
ucLed[0]=1;
}
void Uart_Proc()
{
if(Uart_num != 0)
{
if(Uart_Buf[0]=='T'&&Uart_Buf[1]=='i'&&Uart_Buf[2]=='m'&&Uart_Buf[3]=='e')
{
Uart_num=0;
sprintf(Uart_Buf,"V:is%.2fV\r\n",V_dat);
Send_String(Uart_Buf);
}
}
}
void Timer0Init(void) //1??@12.000MHz
{
AUXR &= 0x7F; //?????12T??
TMOD &= 0xF0; //???????
TL0 = 0x18; //??????
TH0 = 0xFC; //??????
TF0 = 0; //??TF0??
TR0 = 1; //???0????
ET0 = 1;
EA = 1;
}
void TimerServer() interrupt 1
{
if(++Key_Slow_Down==10) Key_Slow_Down=0;
if(++Seg_Slow_Down==500) Seg_Slow_Down=0;
if(++Seg_Pos==8) Seg_Pos=0;
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}
void UartServer() interrupt 4
{
if(RI == 1)
{
RI = 0;
Uart_Buf[Uart_num]=SBUF; //½ÓÊÕÖÃ1£¬È»ºóÖÃ0£¬È»ºó°Ñ·¢Ë͵Ķ«Î÷·Åµ½Êý×éÀï
Uart_num++;
}
}
void main()
{
Set_Rtc(ucRtc);
Init();
EMMPROM_Read(&V_Disp,0,1);
Timer0Init();
UartInit();
while(1)
{
Uart_Proc();
Seg_Proc();
Led_Proc();
Key_Proc();
}
}
最后的几天搞定这一篇,明白所有的使用方法,注意的是内存函数那可能出现显示问题,注意需要那个值放入,哪个值显示,可以进行切换尝试一下
同时注意定时器是否有打开,使用什么中断
对于按键长按,如果让他跳的话,就会跳的很快,如果加上延时的话,就没办法显示,所以我在按键中又进行了显示
if(Key_down == 15)
Time_Flag=1;
if(count<500)
{
if(Key_up == 15)
{
Time_Flag=count=0;
temp++;
}
}
else
{
if(Key_old == 15)
{
Delay500ms();
Seg_Buf[0]=11;
Seg_Buf[6]=temp/10;
Seg_Buf[7]=temp%10;
temp++;
if(temp==100)
temp =99;
}
if(Key_up == 15)
Time_Flag=count=0;
}