历史上的今天
今天是:2025年02月10日(星期一)
2020年02月10日 | 用51单片同时测温度(DS18B20)和频率(外部中断测)
2020-02-10 来源:51hei
void main()//主函数
{
delay1ms(1000);
lcd_init();//液晶显示初始化
init_play();
while(1)
{
EA=0; //因DS18B20对时序要求高且受中断影响,故先关闭总中断
read_temp();//读取温度
ds1820disp();//显示
CT_init();//定时计数器初始化
EA=1;//开总中断
EX0=1;//允许外部中断
IT0=1;//设置外部中断方式为下降沿触发
P3=0xff;
t0=(u*65536+x)*(12/22.1);//计算脉冲时间宽度(单位:ms)
f=1000000/(2*t0);//计算频率
if(f>8000&&tflag==1)
init_play1(); //显示Frozen
else init_play2(); //显示Not frozen
}
}
这是主函数,初步怀疑是中断测频率时和温度传感器读取数据相影响,怎么解决 ?
方法1:读频率实时性要求不高的话,就开这个关那个,轮流来,其他没招了
先测1秒温度,然后测1秒频率,再测一秒温度?
方法2:我给你个参考程序,也是单总线的数据采集(时钟11.0592)。
在你的主循环中不要关闭中断,调用读温度时,有校验码确定数据的有效性(如果读温度程序中间有中断,数据可能会是无效的)。
#include
#include "public.h"
sbit DS2401Bus = P3^5;
//DS2401.c
// 首先对单总线发复位:
// 总线保持低电平超过480us;总线上的所有器件将复位
// 主机释放总线,并进入接收模式
// 从机等待15-60us,接着拉低总线60-240us,以产生应答脉冲
// 写0x33H命令: 仅适合于单节点(读ROM[0x33]命令)
// 所有写(0或1)时隙至少需要60us 且在两次独立的写时隙之间至少需要1us的恢复时间
// 两种写时隙均起始于主机拉低总线
// 写1时隙: 主机在拉低总线后接着必须在15us之内释放总线,由5k上拉电阻将总线拉至高电平
// 写0时隙: 主机拉低总线后只需在整个时隙期间保持低电平即可至少60us
// -- 在写时隙起始后15-60us期间,单总线器件采样总线电平状态(0或1)
// 读时隙
// 器件仅在主机发出读时隙时才向主机传输数据。所以在主机发出读数据命令后必须马上产生读时隙
// 所有读时隙至少需要60us 且在两次独立的读时隙之间至少需要1us的恢复时间
// 每个读时隙都由主机发起,至少拉低总线1us
// 在主机发起读时隙之后单总线器件才开始在总线上发送0或1
// 从机发出的数据在起始时隙之后保持有效时间15us
// 因而,主机在读时隙期间必须释放总线并且在时隙起始后的15us之内采样总线状态
//
#pragma ot(4,SPEED)
void delay_500us(void)
{
unsigned char data i;
for(i = 0; i < 56; i++) ;
}
void delay_250us(void)
{
unsigned char data i;
for(i = 0; i < 28; i++) ;
}
void delay_90us(void)
{
unsigned char data i;
for(i = 0; i < 9; i++) ;
}
void delay_60us(void)
{
unsigned char data i;
for(i = 0; i < 6; i++) ;
}
unsigned char InitDS2401(void) //复位DS2401
{
unsigned char tmp;
DS2401Bus = 0; // 输出:0;总线保持低电平超过480us
delay_500us(); // 498us
DS2401Bus = 1; // 释放总线,由5k上拉电阻将总线拉至高电平
delay_60us(); // 64us,等待器件发出应答脉冲
tmp = DS2401Bus; // 检查应答脉冲
delay_250us(); // 255us,延时240us以上
if(tmp) // 读取数据
return 0;
else
return 1;
}
void WriteDS2401(unsigned char d)//写2401命令
{
unsigned char i;
for(i=0;i<8;i++) {
DS2401Bus = 0; // 主机在拉低总线后接着必须在15us之内释放总线
_nop_(); _nop_(); _nop_(); // 每个nop估计耗时 1.085us
if(d & 1) { // 输出:数据位
DS2401Bus = 1;
}
d >>= 1;
delay_60us(); // 至少保持60us
DS2401Bus = 1; // 将总线拉至高电平, 至少需要1us的恢复时间
_nop_();_nop_();_nop_();
}
}
unsigned char ReadDS2401() //读2401数据
{
unsigned char i,d;
for(i=0;i<8;i++) {
d >>= 1;
DS2401Bus = 0; // 至少拉低总线1us
_nop_();_nop_();_nop_();
DS2401Bus = 1; // 释放总线
_nop_();_nop_();_nop_();_nop_();_nop_();
if(DS2401Bus == 1) d |= 0x80; // 读取数据
delay_90us(); // 90us
}
return d;
}
unsigned char crctest() //进行CRC校验
{
unsigned char i1, i2, crc=0;
for(i1=0; i1<8; i1++) {
crc ^= DS2401IDBuf[i1];
for(i2=0; i2<8; i2++) {
if (crc & 0x01)
crc = (crc >> 1) ^ 0x8C;
else
crc >>= 1;
}
}
return (crc);
}
unsigned char ReadRS2401ID() //读出DS2401的
{
unsigned char i;
if (!InitDS2401()) return(0);
WriteDS2401(0x33);
for(i=0;i<8;i++) DS2401IDBuf[i]=ReadDS2401();
if (crctest() != 0) return(0);
return(1); //CRC校验成功
}
史海拾趣
|
Win ce 5.0 下SD卡驱动程序中的"sdbusdriver" 微软自带的Bus层驱动程序中,在其下的文件sdhceventhandlers.cpp下有一个slotstatuschange函数,这个函数是一个死循环专门负责卡插入拨出时的加载和卸载还有设备中断,在循环中有一个pWorkItem->GetMessage(),用来等待消息,以控制循环。有没有高手 ...… 查看全部问答> |
|
我使用USART1模块进行串口通讯,但调试的时候发现程序进不了中断。 相关代码: #include \"msp430x14x.h\" #define uchar unsigned char #define uint unsigned int #define URXD1 BIT7 #define UTXD1 BIT6 uchar dataSedBuffer[100] ...… 查看全部问答> |
|
我用单片机IO口模拟RS232通讯,单片机给PC机传数据。但是我不知道PC机的串口数据是如何读取的,因此我就不知道如何发送0和1.比如,串口采用的N8.1格式的数据吗?要发送一个数字或者一个字母(如A),发送的是ASCII码吗?先发送低位还是高位?能具体 ...… 查看全部问答> |
|
请教:关于LSD-MSP430PRGS-IIIA编程器的BSL密码文件,在说明书中提到 “BSL 密码文件:装载代码的密码文件,芯片熔丝烧掉以后,程序需要更新,但是不希望信息FLASH 里的数据被擦除的情况下使用这种方法,进行这种操作时,务必需要执行以下操作:加 ...… 查看全部问答> |
|
请教:Quartus6.0中打开SOPC打不开,出现at.java.awt....(Unknown Source) 请教各路高手:Quartus6.0中点击SOPC打不开,出现很多诸如at.java.awt....(Unknown Source) 注:Nois 已经安装。 此问题困我很久了,望高手指点迷津。 ...… 查看全部问答> |
|
nowECC v2.17 使用疑问,芯片TMS570LS1227-144脚 我是用TMS570LS1227-144脚芯片,在生成ECC时如下配置不明确, memory map 应该是_f021 8M还是16M? 若使用命令“nowecc -i file. out -a -o fileecc.out -f021 8M”则生成附加ECC的.out文件。 利用这种方案生成.out文件烧录至FLASH中是否合理! ...… 查看全部问答> |




