前言:
国赛第十届是有一定难度的,需要达到使用多个模块且不冲突,其中有超声波、温度、串口、eeprom等等。话不多说,直接开始。
题目:![](https://img-blog.csdnimg.cn/direct/5ec61eacd1ce44be9d3c82ed567993a4.png)
解析(伪代码:
--> typedef unsigned char u8;
--> typedef unsigned int u16;
超声波模块:
/*定义tx,rx引脚*/
sbit tx = P1^0;
sbit rx = P1^1;
void Delay14us()//@12.000MHz
{
//正常为12us,出现异常情况可以试试13us,14us
unsigned char i;
_nop_();
_nop_();
i = 38;
while (--i);
}
void sendwave()
{
u8 i;
for ( i=0; i<8; i++)
{
tx = 0;
Delay14us();
tx = 1;
Delay14us();
}
}
void dist_read() //超声波测距
{
u16 time;
CMOD = 0x00; //采用PCA(可自行查手册查看
CH = CL = 0;
EA = 0; //在一定程度上减少误差
sendwave();
EA = 1; CR=1;
while (rx && !CF);
CR = 0;
if (CF == 0)
{
time = CH;
time = (time<<8)|CL;
distance = time*0.017;
if(distance>99) distance=99;
}else{
CF = 0;
distance = 99;
}
}
DS18B20:
/*
导入官方onewire.c
写出onewire.h
*/
void delay(u16 a)
{
while(a--);
}
void ds18b20_init()
{
u8 i;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
for ( i=0; i<8; i++ )
{
delay(60000); //消除上电读到85
}
}
void ds18b20_read() //温度读取
{
u8 MSB,LSB;
u16 Data;
if(temp_down_t) return;
temp_down_t = 1;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
Data = MSB;
Data = (Data<<8)|LSB;
if((Data&0xf800) == 0x00) //判断温度是否大于0摄氏度
{
Temp_t = Data*0.0625;
temp = Temp_t*100;
}
}
DAC输出:
void DA_Output(unsigned char num) //DA转换
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(num);
I2CWaitAck();
I2CStop();
}
unsigned char AD_Input(unsigned char addr) //AD转换输出
{
unsigned char Data=0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
Data = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return Data;
}
//*****************************************
void dac_ouput() //dac处理函数
{
u8 Data; //即要输出的值
if(dac_output)
{
if(distance<=dist_para_t)
{
Data = 102;
}else{
Data = 204;
}
DA_Output(Data); //输出
}else{
DA_Output(20.4);
}
}
串口通信:
/*
波特率发生器:定时器1
isp生成串口函数;
补充ES=1;EA=1;
*/
void UartInit(void) //4800bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xCC; //设定定时初值
TH1 = 0xFF; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1;
ES = 1;
}
void sendbyte(u8 Data) //发送一个字节
{
SBUF = Data;
while(TI==0); //TI==1时,数据发送完成,退出循环
TI = 0;
}
void send_string(char* str) //发送字符串
{
while(*str != '\0')
{
sendbyte(*str++);
}
}
//********************************
xdata u8 rx_buff[12];//放置在xdata,减少ram占用
xdata u8 tx_buff[12];
u8 sys_cli=0;//如果为1,10ms计时
u8 uar_10ms=0;//接收中断、串口处理清0,超过10ms没接收数据 即处理指令
void uart_work() //串口处理函数
{
u8 i=0;
if(!rx_cnt) return;
if(uar_10ms>=10)
{
sys_cli = 0;
uar_10ms = 0;
if(rx_buff[0]=='S' && rx_buff[1]=='T') //接收字符串->判断
{
sprintf(tx_buff,"$%2d,%4.2f\r\n",distance,Temp_t);
}else if(rx_buff[0]=='P' && rx_buff[1]=='A' && rx_buff[2]=='R' && rx_buff[3]=='A'){
sprintf(tx_buff,"#%d,%d\r\n",(int)dist_para_t,(int)temp_para_t);
}else{
sprintf(tx_buff,"ERROR\r\n");
}
send_string(tx_buff);
for(i=0; i<rx_cnt; i++)
{
rx_buff[i] = 0;
tx_buff[i] = 0;
}
rx_cnt = 0;
}
}
void Uart_Routine() interrupt 4 //串口中断
{
if(RI==1)
{
sys_cli = 1;
uar_10ms = 0;
rx_buff[rx_cnt++] = SBUF;
RI = 0;
}
}
EEPROM:
由于参数变动次数范围为0-65535,可以取高八位为一字节,低八位为一字节,保存到两个地址。
void at24c02_write(unsigned char addr,date) //参数:地址,数据
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(date);
I2CWaitAck();
I2CStop();
}
void write_stock()
{
u8 high,low;
if(stoc_down_t) return; //25ms写入一次
stoc_down_t = 1;
if(mode==1)
{
if((temp_para_t!=temp_para)||(dist_para_t!=dist_para)) //判断参数是否改变
{
temp_para_t = temp_para;
dist_para_t = dist_para;
bian_cnt++;
high = (u8)(bian_cnt>>8);
low = (u8)bian_cnt;
at24c02_write(0x01,high);
at24c02_write(0x00,low);
Delay5ms();
}
}
}
长按的实现:
/*
以按键S13为例子,实现长按
*/
u8 key_read() //按键响应
{
u8 temp=0;
ET0 = 0;
P35=0;P34=1;
if(P32 == 0) temp = 13;
if(P33 == 0) temp = 12;
P35=1;P34=0;
if(P32 == 0) temp = 17;
if(P33 == 0) temp = 16;
ET0 = 1;
return temp;
}
void key_work() //按键处理函数
{
u8 high,low;
if(key_down_t) return; //10ms进一次函数,消除按键抖动
key_down_t = 1;
key_val = key_read();
key_down = key_val&(key_val^key_old);//下降沿
key_up = ~key_val&(key_val^key_old);
key_old = key_val;
if(key_down == 13) //按键按下,标志为1
{
long_an = 1;
}
if(key_up == 13) //按键抬起
{
long_an = 0;
time1s = 0;
if(!flag1s) //判断flag1s是否为1
{
if(++mode==3) mode=1;
modepro = 1;
}
if(flag1s)
{
flag1s = 0;
if(dac_output) dac_output=0;else dac_output=1;
}
}
}
void Timer_Routine() interrupt 1
{
if(++key_down_t == 10) key_down_t = 0;
if(long_an) time1s++;
if(time1s>=1000) //若时间超过1s,flag1s=1;
{
time1s=0;
flag1s=1;
}
}
完整源码:
main.c
#include <STC15F2K60S2.H>
#include "configure.h"
#include "onewire.h"
#include "iic.h"
#include "stdio.h"
//****************************
sbit tx = P1^0;
sbit rx = P1^1;
u8 temp_down_t = 0;
u8 smg_down_t = 0;
u8 csb_down_t = 0;
u8 key_down_t = 0;
u8 stoc_down_t = 0;
u8 key_val,key_old,key_down,key_up;//按键读取
u8 mode=1,modepro=1;
//-----
u16 temp;
float Temp_t;//读取温度浮点数保存
u16 distance;//读取距离
u16 bian_cnt = 0;//变动次数
u8 temp_para_t = 30,temp_para = 30;//参数值
u8 dist_para_t = 35,dist_para = 35;
u8 led_state=0xff;//led灯的状态
//----
u8 rx_cnt=0;
xdata u8 rx_buff[12];//放置在xdata,减少ram占用
xdata u8 tx_buff[12];
//-----
bit dac_output=1;//1为启动
bit long_an=0;//长按标志位
bit flag1s=0;//1s标志位
u16 time1s;
//-----
u8 sys_cli=0;//如果为1,10ms计时
u8 uar_10ms=0;//接收中断、串口处理清0,超过10ms没接收数据 即处理指令
//***********Init*****************
void delay(u16 a)
{
while(a--);
}
void sendbyte(u8 Data)
{
SBUF = Data;
while(TI==0);
TI = 0;
}
void send_string(char* str)//发送字符串
{
while(*str != '\0')
{
sendbyte(*str++);
}
}
u8 key_read() //按键响应
{
u8 temp=0;
ET0 = 0;
P35=0;P34=1;
if(P32 == 0) temp = 13;
if(P33 == 0) temp = 12;
P35=1;P34=0;
if(P32 == 0) temp = 17;
if(P33 == 0) temp = 16;
ET0 = 1;
return temp;
}
void sendwave()
{
u8 i;
for ( i=0; i<8; i++)
{
tx = 0;
Delay14us();
tx = 1;
Delay14us();
}
}
void ds18b20_init()
{
u8 i;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
for ( i=0; i<8; i++ )
{
delay(60000);
}
}
//+++++++++++Work+++++++++++
//**************************
void uart_work() //串口处理函数
{
u8 i=0;
if(!rx_cnt) return;
if(uar_10ms>=10)
{
sys_cli = 0;
uar_10ms = 0;
if(rx_buff[0]=='S' && rx_buff[1]=='T')
{
sprintf(tx_buff,"$%2d,%4.2f\r\n",distance,Temp_t);
}else if(rx_buff[0]=='P' && rx_buff[1]=='A' && rx_buff[2]=='R' && rx_buff[3]=='A'){
sprintf(tx_buff,"#%d,%d\r\n",(int)dist_para_t,(int)temp_para_t);
}else{
sprintf(tx_buff,"ERROR\r\n");
}
send_string(tx_buff);
for(i=0; i<rx_cnt; i++)
{
rx_buff[i] = 0;
tx_buff[i] = 0;
}
rx_cnt = 0;
}
}
void led_work()
{
if(temp>temp_para_t*100)
{
led_state &= 0xfe;
}else{
led_state |=~0xfe;
}
if(distance<dist_para_t)
{
led_state &= 0xfd;
}else{
led_state |=~0xfd;
}
if(dac_output)
{
led_state &= 0xfb;
}else{
led_state |=~0xfb;
}
HC138_Init(4,led_state);
}
void dac_ouput() //dac处理函数
{
u8 Data;
if(dac_output)
{
if(distance<=dist_para_t)
{
Data = 102;
}else{
Data = 204;
}
DA_Output(Data);
}else{
DA_Output(20.4);
}
}
void write_stock()
{
u8 high,low;
if(stoc_down_t) return;
stoc_down_t = 1;
if(mode==1)
{
if((temp_para_t!=temp_para)||(dist_para_t!=dist_para))
{
temp_para_t = temp_para;
dist_para_t = dist_para;
bian_cnt++;
high = (u8)(bian_cnt>>8);
low = (u8)bian_cnt;
at24c02_write(0x01,high);
at24c02_write(0x00,low);
Delay5ms();
}
}
}
void dist_read() //超声波测距
{
u16 time;
CMOD = 0x00;
CH = CL = 0;
EA = 0;
sendwave();
EA = 1; CR=1;
while (rx && !CF);
CR = 0;
if (CF == 0)
{
time = CH;
time = (time<<8)|CL;
distance = time*0.017;
if(distance>99) distance=99;
}else{
CF = 0;
distance = 99;
}
}
void ds18b20_read() //温度读取
{
u8 MSB,LSB;
u16 Data;
if(temp_down_t) return;
temp_down_t = 1;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
Data = MSB;
Data = (Data<<8)|LSB;
if((Data&0xf800) == 0x00) //判断温度是否大于0摄氏度
{
Temp_t = Data*0.0625;
temp = Temp_t*100;
}
}
void key_work() //按键处理函数
{
u8 high,low;
if(key_down_t) return;
key_down_t = 1;
key_val = key_read();
key_down = key_val&(key_val^key_old);//下降沿
key_up = ~key_val&(key_val^key_old);
key_old = key_val;
if(key_down == 13)
{
long_an = 1;
}
if(key_up == 13)
{
long_an = 0;
time1s = 0;
if(!flag1s)
{
if(++mode==3) mode=1;
modepro = 1;
}
if(flag1s)
{
flag1s = 0;
if(dac_output) dac_output=0;else dac_output=1;
}
}
if(key_down == 12)
{
long_an = 1;
}
if(key_up == 12)
{
long_an = 0;
time1s = 0;
if(!flag1s)
{
if(mode==1)
{
if(++modepro==4) modepro=1;
}
if(mode==2)
{
if(++modepro==3) modepro=1;
}
}
if(flag1s)
{
flag1s = 0;
bian_cnt = 0;
high = (u8)(bian_cnt>>8);
low = (u8)bian_cnt;
at24c02_write(0x01,high);
at24c02_write(0x00,low);
Delay5ms();
}
}
if(key_down == 16) //减
{
if(mode==2)
{
if(modepro==1)
{
if(temp_para>=2) temp_para -= 2;else temp_para = 0;
}
if(modepro==2)
{
if(dist_para>=5) dist_para -= 5;else dist_para = 0;
}
}
}
if(key_down == 17)
{
if(mode==2)
{
if(modepro==1)
{
if(temp_para<=97) temp_para += 2;else temp_para = 99;
}
if(modepro==2)
{
if(dist_para<=94) dist_para += 5;else dist_para = 99;
}
}
}
}
void smg_work() //数码管显示函数
{
static u8 dac=0;
if(smg_down_t) return;
smg_down_t = 1;
//******
if(++csb_down_t == 25)
{
csb_down_t = 0;
dist_read();
}
if(++dac==5)
{
dac = 0;
dac_ouput();
}
//******
if(mode == 1) //数据界面
{
if(modepro == 1) //温度
{
smg_data[0] = 0xc6; smg_data[1] = 0xff;
smg_data[2] = 0xff; smg_data[3] = 0xff;
smg_data[4] = SMG_NoDot[temp/1000];
smg_data[5] = SMG_Dot[temp/100%10];
smg_data[6] = SMG_NoDot[temp/10%10];
smg_data[7] = SMG_NoDot[temp%10];
}
if(modepro == 2) //距离
{
smg_data[0] = 0xc7; smg_data[1] = 0xff;
smg_data[2] = 0xff; smg_data[3] = 0xff;
smg_data[4] = 0Xff; smg_data[5] = 0xff;
smg_data[6] = SMG_NoDot[distance/10];
smg_data[7] = SMG_NoDot[distance%10];
}
if( modepro == 3) //变更次数
{
smg_data[0] = 0xc8; smg_data[1] = 0xff;
smg_data[2] = 0xff;
if(bian_cnt>9999) smg_data[3] = SMG_NoDot[bian_cnt/10000];else smg_data[3] = 0xff;
if(bian_cnt>999) smg_data[4] = SMG_NoDot[bian_cnt/1000%10];else smg_data[4] = 0xff;
if(bian_cnt>99) smg_data[5] = SMG_NoDot[bian_cnt/100%10];else smg_data[5] = 0xff;
if(bian_cnt>9) smg_data[6] = SMG_NoDot[bian_cnt/10%10];else smg_data[6] = 0xff;
smg_data[7] = SMG_NoDot[bian_cnt%10];
}
}
if(mode == 2) //参数界面
{
if(modepro == 1) //温度参数
{
smg_data[0] = 0x8c; smg_data[1] = 0xff;
smg_data[2] = 0xff; smg_data[4] = 0xff;
smg_data[5] = 0xff;
smg_data[3] = SMG_NoDot[modepro];
smg_data[6] = SMG_NoDot[temp_para/10];
smg_data[7] = SMG_NoDot[temp_para%10];
}
if(modepro == 2) //距离参数
{
smg_data[0] = 0x8c; smg_data[1] = 0xff;
smg_data[2] = 0xff; smg_data[4] = 0xff;
smg_data[5] = 0xff;
smg_data[3] = SMG_NoDot[modepro];
smg_data[6] = SMG_NoDot[dist_para/10];
smg_data[7] = SMG_NoDot[dist_para%10];
}
}
}
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 UartInit(void) //4800bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xCC; //设定定时初值
TH1 = 0xFF; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1;
ES = 1;
}
void system_init()
{
HC138_Init(4,0xff);
HC138_Init(5,0x00);
Timer0Init();
UartInit();
ds18b20_init();
}
void main()
{
system_init();
while(1)
{
ds18b20_read();
write_stock();
uart_work();
key_work();
smg_work();
}
}
void Timer_Routine() interrupt 1
{
if(++smg_down_t == 10) smg_down_t = 0;
if(++temp_down_t == 200) temp_down_t = 0;
if(++key_down_t == 10) key_down_t = 0;
if(++stoc_down_t==25) stoc_down_t = 0;
if(long_an) time1s++;
if(sys_cli) uar_10ms++;
if(time1s>=1000)
{
time1s=0;
flag1s=1;
}
led_work();
smg_bit();
}
void Uart_Routine() interrupt 4
{
if(RI==1)
{
sys_cli = 1;
uar_10ms = 0;
rx_buff[rx_cnt++] = SBUF;
RI = 0;
}
}
configure.c
#include <STC15F2K60S2.H>
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
code u8 SMG_NoDot[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
//1 2 3 4 5 6 7 8 9
code u8 SMG_Dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
// 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
u8 smg_data[8]={255,255,255,255,255,255,255,255};
void Delay14us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 38;
while (--i);
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void HC138_Init(u8 num1,num2)
{
P2 = P2&0x1f;
P0 = num2;
switch(num1)
{
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;
}
P2 = P2&0x1f;
}
void smg_bit()
{
static u8 pos=0;
HC138_Init(7,0xff);
HC138_Init(6,0x01<<pos);
HC138_Init(7,smg_data[pos]);
if(++pos==8) pos=0;
}
configure.h
#ifndef __CONFIGURE_H
#define __CONFIGURE_H
typedef unsigned char u8;
typedef unsigned int u16;
extern code u8 SMG_NoDot[10];
extern code u8 SMG_Dot[10];
extern u8 smg_data[8];
void Delay14us(); //@12.000MHz
void Delay5ms(); //@12.000MHz
void HC138_Init(u8 num1,num2);
void smg_bit();
#endif
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "intrins.h"
#define DELAY_TIME 10
sbit sda=P2^1;
sbit scl=P2^0;
//
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);
}
void DA_Output(unsigned char num)
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(num);
I2CWaitAck();
I2CStop();
}
unsigned char AD_Input(unsigned char addr)
{
unsigned char Data=0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
Data = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return Data;
}
void at24c02_write(unsigned char addr,date)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(date);
I2CWaitAck();
I2CStop();
}
iic.h
#ifndef __IIC_H
#define __IIC_H
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
void DA_Output(unsigned char num);
unsigned char AD_Input(unsigned char addr);
void at24c02_write(unsigned char addr,date);
#endif
onewire.c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.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;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
注:以上自己纯手搓,可能存在部分的问题,希望大家给予指正。