本次测试包含基本底层——在不冲突的条件下,其包含了数码管, 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~5Seg_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;}