#include<stc15f2k60s2.h>
//0-9的字段码
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//0123456789
//在驱动文件中写的函数要在.h头文件中定义
DS18B20温度
改时间!!!onewire.c
!!!t = t *12;!!!delay(200)
// 注意取值范围以及.h文件中的改写
// 正常0.0625
// 一位小数0.625(取三个整数)
// 两位小数6.25(取四个整数)
CCH:跳过ROM指令
44H:温度转换指令
BEH:读暂存器指令
12位数据中高8位是整数数据,低四位是小数数据
//修改原Delay_OneWire
void Delay_OneWire(unsigned int t) //STC12C5260S2
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//两位整数
unsigned char ReadTemp(){
unsigned char low,high;
char temp;
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
//相当于0.0625*16 = 1;不需要再乘以0.0625了,并且还得到了整数
temp = high<<4;
temp = temp | low>>4;
return temp;
}
//四位数,xx.xx数码管显示要带小数点
unsigned int ReadTemp(){
unsigned int temp;
unsigned char low,high;
InitDS18B20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//开启温度转换
Delay_OneWire(200);//温度转换延时
InitDS18B20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);//读取温度
//低位在前高位在后
low = Read_DS18B20();
high = Read_DS18B20();
temp = high<<8;
temp |= low;
temp = temp*25;
return (temp>>2);//等价于temp*6.25 精度是0.0625
}
DisplayData[4]=table[temp%10000/1000];
DisplayData[5]=table[temp%1000/100]&0x7f;//带上小数点
DisplayData[6]=table[temp%100/10];
DisplayData[7]=table[temp%10];
DS1302时钟
WP 0x00关闭写保护(写数据的时候)
WP 0x80打开写保护(读数据的时候)
0x8e 写保护寄存器的位置
写操作秒分时0x80 0x82 0x84...
读操作秒分时0x81 0x83 0x85...
- 在.h文件中写extern unsigned char TIME[]
- 注意名字不要写错
//秒分时日月周年
unsigned char Write_Ds1302_addr[]={0x80,0x82,0x84}; //秒分时
unsigned char Read_Ds1302_addr[]={0x81,0x83,0x85}; //秒分时
unsigned char TIME[7] = {0,0x12, 0x12}; //秒分时
//初始化函数,设定初始时间
void DS1302Init()
{
uchar i;
Write_Ds1302_Byte(0x8e,0x00); //0x00关闭写保护
for (i=0;i<3;i++)//初始化时分秒
{
Write_Ds1302_Byte(Write_Ds1302_addr[i],TIME[i]);
}
Write_Ds1302_Byte(0x8e,0x80); //0x80写保护
}
//读时间
void DS1302ReadTime()
{
uchar i;
for (i=0;i<3;i++)
{
TIME[i]=Read_Ds1302_Byte (Read_Ds1302_addr[i]);
}
}
//显示数组并且将BCD码转化成16进制直接读16进制
DS1302ReadTime();
DisplayData[0] = table[TIME[2]/16]; //时
DisplayData[1] = table[TIME[2]&0x0f];
DisplayData[2] = 0xbf;
DisplayData[3] = table[TIME[1]/16]; //分
DisplayData[4] = table[TIME[1]&0x0f];
DisplayData[5] = 0xbf;
DisplayData[6] = table[TIME[0]/16]; //秒
DisplayData[7] = table[TIME[0]&0x0f];
//或者设置时间的时候把十进制转化成16进制BCD码
void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao)
{
Write_Ds1302_Byte(0x8e,0x00);//关闭保护位
Write_Ds1302_Byte(0x80,(miao/10)*16+miao%10);//设置秒
Write_Ds1302_Byte(0x82,(fen/10)*16+fen%10);//设置分
Write_Ds1302_Byte(0x84,(shi/10)*16+shi%10);//设置小时
Write_Ds1302_Byte(0x8e,0x80);//打开保护位
}
//然后把其中的转化成十进制
shi_temp =Read_Ds1302_Byte(0x85);
fen_temp=Read_Ds1302_Byte(0x83);
miao_temp=Read_Ds1302_Byte(0x81);
shi = shi_temp/16*10+shi_temp%16;
fen = fen_temp/16*10+fen_temp%16;
miao = miao_temp/16*10+miao_temp%16;
AT24C02 EEPROM
板载一个24C02,外设写的地址是0xA0
板载一个24C02,外设读的地址是0xA1
//修改i2c.c中somenop中的时延,60个_nop_();
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();}
//把所有的IIC_Delay(DELAY_TIME);换成somenop
void Write_AT24C02(unsigned char addr,unsigned char dat)
{
IIC_Start();//打开总线
IIC_SendByte(0xa0);//找到24C02地址
IIC_WaitAck();//等待响应
IIC_SendByte(addr);//发送地址
IIC_WaitAck();//等待响应
IIC_SendByte(dat);//发送数据
IIC_WaitAck();//等待响应
IIC_Stop();//停止总线
somenop;//延时
}
unsigned char Read_AT24C02(unsigned char addr)
{
unsigned char dat;
IIC_Start();//打开总线
IIC_SendByte(0xa0);//发送24C02总线地址
IIC_WaitAck();//等待响应
IIC_SendByte(addr);//发送存储数据地址
IIC_WaitAck();//等待响应
IIC_Start();//打开总线
IIC_SendByte(0xa1);//发送地址读
IIC_WaitAck();//等待响应
dat=IIC_RecByte();//获取数据
IIC_SendAck(1);//发送应答数据 0应答 1非应答
IIC_Stop();//停止总线
return dat;
}
//输入的是0,取反了0为非应答,原驱动的1是非应答
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
矩阵键盘
蓝桥杯的开发板没有引出P36和P37 P4^2 -> P3^6; P4^4 -> P3^7
//一列一列扫描
P3=0x7f;
P42=1;
P44=0;
temp=P3;
temp&=0x0f;
if (temp!=0x0f) //检测低四位
{
delay(10);
temp=P3;
temp&=0x0f; //消抖
if (temp!=0x0f)
{
temp=P3;
switch (temp) //temp的与运算影响不带P3,所以如此检测
{
case (0x7e):KeyValue=0;break;
case (0x7d):KeyValue=4;break;
case (0x7b):KeyValue=8;break;
case (0x77):KeyValue=12;break;
default:break;
}
while (temp!=0x0f)
{//复位,等待下次按下
temp=P3;
temp&=0x0f;
}
}
PCF8591 AD
主机地址0x90
Rb2通道位置0x03
控制字节的第 0 位和第 1 位就是通道选择位了,00、01、10、11 代表了从 0 到 3 的一共4 个通道选择。
//channel 通道位置 0x03为Rb2
void InitPCF8591(unsigned char channel){
IIC_Start();//打开总线
IIC_SendByte(0x90);//发送总线位置
IIC_WaitAck();//等待响应
IIC_SendByte(channel);//发送信道
IIC_WaitAck();//等待响应
IIC_Stop();//停止
}
unsigned char ReadPCF8591(){
unsigned char dat;
IIC_Start();//打开总线
IIC_SendByte(0x91);//发送总线位置,读
IIC_WaitAck();//等待响应
dat = IIC_RecByte();//读取数据
IIC_SendAck(1);//发送信号,1为非应答
IIC_Stop();//停止总线
return dat;//返回数据
}
PCF8591 DA
1.DA输出Vout= VREF/255*dat; 2.0x90 PCF8591地址,写 3.0x40 DAC输出模式
//输入数字量,范围是0-255
//dat = (volt*255)/5
void WritePCF8591(unsigned char dat){
IIC_Start();//打开总线
IIC_SendByte(0x90);//发送总线位置,写
IIC_WaitAck();//等待响应
IIC_SendByte(0x40);//DAC输出模式
IIC_WaitAck();//等待响应
IIC_SendByte(dat);//DAC发送相应的数据
IIC_WaitAck();//等待响应
IIC_Stop();//关闭总线
}
超声波模块
利用Trig发送8个频率为40kHz的方波,此时开启定时器
直到Echo接收到返回的超声波(接收信号为Echo的下降沿),停止定时器,采集到的时间便是求出超声波模块到障碍物之间的距离的关键.
距离 = 340*(时间t) (往返2) = (定时器时间t)*0.017
0.017 = (2^4+1)/1000 = 2^4/1000 + 0.001 约为 2^4/1000, 在精度要求不高的情况下可以约为 2^4/1024 = 2^4/2^10 = 2-6,整理到C语言2-6对应为>>6(右移6位), 这样的话对超声波的数据处理速度可以提高几十倍
//初始化时将trig和echo端口置低, 然后给trig发送8个40KHz的方波f=40KHz T=1/40K=12.5us 则使用延迟12us来实现
//打开定时器开始定时, 捕捉echo的下降沿,当捕捉到下降沿时, 读出定时器的时间, 这就是超声波在空气中传播的时间
sbit Trig=P1^0;
sbit Echo=P1^1;
void Delay12us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
void Sonic_Wave() //发送8个40KHz的方波
{
unsigned char i;
for (i=0;i<8;i++) //发送8个方波
{
Trig=1;
Delay12us();
Trig=0;
Delay12us();
}
}
void Sonic_Distance() //距离测量
{
unsigned int time; //记录时间
Sonic_Wave(); //发送波
TR1=1; //启动定时器
while ((Echo==1)&&(TF1==0)); //等待接收到波(Echo检测到下降沿)或者定时器溢出,时间过长
TR1=0; //关闭定时器
/*计算距离:
定时器是1us计数加一, 求声速传播距离公式为 X = 340*t/2 (单位为 m)
将数码管的显示值转换为 cm ,乘以100, 获得的时间单位为us, 需要转化为s,除以1,000,000
故,Sonic_Distance = Sonic_Distance*0.017; 为了使处理速度加快,需要转化为整数操作
0.017 = 17/10/100
*/
if (TF1==0) //正常范围之内
{
time=TH1;
time=(time<<8)|TL1;//计算时间us
// Distance=time*0.017
// 0.017 = 17/1000 = (2^4+1)/1000 = 2^4/1000 + 0.001 约为 2^4/1000 在精度不高的情况下 约为 2^4/1024 = 2^4/2^10 = 2^-6
Distance = time>>6; 进行处理速度的提高,运算
}
else
{
TF1=0;
Distance=999;
}
TH1=0; TL1=0; //恢复定时器
}
NE555方波发生器
定时和计数只是触发来源不同(时钟信号和外部脉冲)其他方面是一样的
使用跳线帽将SIGNAL与P34相连, 则信号输出端与定时器0的计数端口相连接了
定时器0是计数功能,P3^4下降就加1,检测其数值

//NE555的方波发生端和定时器0P3^4的接口在一起, 我们需要先开启定时器1,再将定时器0变为计数器, 在定时器1的规定时间内去统计方波下降沿的次数,根据求频率的公式便可以得出频率
//CT107D已经为我们准备好了NE555方波发生器的电路,我们只需要旋转Rb3电位器就可以
//定时器0使用计数模式,8位自动初值重装的计数器,初值为0xff,检测到就触发
unsigned int NE555_Falling,NE555_Time,NE555_Frequency; //下降沿个数 555的时间 频率
//TH0=0xFF; TL0=0xFF; 定时器0做计数器,计数器初值为满值, 这样当检测到一次下降沿时就可以触发中断
//定时器1定时中端一次为5ms
void Timer0() interrupt 1 //定时器0作为计数器,当检测到下降沿时触发中断
{
NE555_Falling++;
}
void Timer1() interrupt 3 //定时器1作为定时器,计算周期
{
TH1=(65536-5000)/256; TL1=(65536-5000)%256; //定时器1定时中端一次为5ms
NE555_Time++;
if (NE555_Time==20) //100ms 计算100ms内NE555发生下降沿的个数,由此求得频率
{
NE555_Frequency = NE555_Falling*10; //频率为1s内发生下降沿的个数,定时为0.1s,则需要*10
NE555_Falling=0;
NE555_Time=0;
}
}
串口通信
计算波特率

str AUXR=0x8e; 51特殊寄存器具体不深究
main(){
UartInit(); //串口初始化
}
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE0; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
ES = 1; //开启串口中断
TR1 = 1; //启动定时器1
EA=1; //总中断打开
}
//串口发送
void uart_sendstring(unsigned char *str)
{
unsigned char *s;//输入的字符串
s = str;//赋值暂存
while(*s != '\0')
{
SBUF = *s; //将数据放进SBUF缓冲器
while(TI == 0); //等待发送数据完成
TI = 0; //清除发送完成标志
s++;
}
}
//串口接收
//定时器接收数据
void InterruptUART() interrupt 4 //串口中断的中断号是四
{
if(RI) //如果接收标志位置一,
{
RI = 0;
P0=SBUF;//接收数据后显示在P0上
//SBUF = SBUF + 1; 就将接收寄存器的值加一再放到发送缓存区里别忘了
//标志位清零,否则就死在这儿了
}
if(TI) //字节发送完毕
{
TI = 0; //清零
}
}




