DS18B20 温度传感器与按键系统笔记
DS18B20 温度传感器
1. 数据读取顺序
- 低8位先读 ,然后读高8位
- 总共读取16位温度数据
2. 通信时序
2.1 写时序(Figure 3)
// 向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0; // 拉低电平开始写时序
DQ = dat & 0x01; // 输出数据位(0或1)
Delay_OneWire(5); // 保持时间
DQ = 1; // 释放总线
dat >>= 1; // 准备下一位
}
Delay_OneWire(5); // 字节间延时
}
2.2 读时序(Figure 4)
// 从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat = 0;
for(i=0;i<8;i++)
{
DQ = 0; // 拉低电平开始读时序
dat >>= 1; // 右移准备接收新位
DQ = 1; // 释放总线,让DS18B20控制
if(DQ) // 如果总线为高电平
{
dat |= 0x80; // 将最高位置1
}
Delay_OneWire(5); // 保持时间
}
return dat; // 返回读取的字节
}
3. 总函数
//读取温度函数,返回温度高低的两个字节
//功能:完成温度转换,返回转换后的温度数据
float rd_temperature(void)
{
unsigned char low,high;//返回温度数据的高低八位
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//进行温度转换
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);//读取温度
low = Read_DS18B20();//读取低位
high = Read_DS18B20();//读取高位
return((high<<8)|low) / 16.0;
}
//因为最小单位 0.0625℃,所以是16.0,防止整除丢失分辨率
4. 定时器中断高效利用
Timer0中断挂载的任务:
- 数码管扫描 :每1ms扫描一位
- 按键消抖 :每10ms读取一次按键状态
- LED PWM :每1ms比较一次
- 闪烁标志翻转 :每500ms翻转一次
按键系统
第一章:按键系统基础
1.1 按键底层原理
- 矩阵按键 :先扫描行,再扫描列
- 独立按键 :4个独立按键(P3.0-P3.3)
1.2 按键读取函数
// 独立按键读取函数
unsigned char Key_Read() {
unsigned char temp = 0;
// 按优先级判断按键(P3.3优先级最高)
if (P33 == 0) // 第4个按键按下
temp = 4;
if (P32 == 0) // 第3个按键按下
temp = 3;
if (P31 == 0) // 第2个按键按下
temp = 2;
if (P30 == 0) // 第1个按键按下
temp = 1;
return temp; // 返回0表示无按键,1-4表示按键编号
}
1.3 三行代码消抖法(核心!)
// 在主循环中调用
Key_Val = Key_Read(); // 1. 读取当前按键值
Key_Down = Key_Val & (Key_Old ^ Key_Val); // 2. 检测按键按下
Key_Up = ~Key_Val & (Key_Old ^ Key_Val); // 3. 检测按键释放
Key_Old = Key_Val; // 4. 保存当前状态
按键应用实例
按键类型1:短按慢加,长按快加(S5)
unsigned int Time_1s_5;
bit Long_Press_5;
unsigned char my_data1;
// 按键处理函数片段
if (Key_Down == 5)
Long_Press_5 = 1; // 标记长按开始
if (Time_1s_5 >= 1000)
{
if (Key_Old == 5)
my_data1++; // 长按一直+1
}
if (Key_Up == 5)
{
if (Time_1s_5 < 1000)
my_data1++; // 短按+1
Long_Press_5 = 0; // 长按结束
Time_1s_5 = 0; // 重置时间
}
按键类型2:长按松手执行任务(S6)
unsigned int Time_1s_6;
bit Long_Press_6;
unsigned char my_data2;
// 按键处理函数片段
if (Key_Down == 6)
Long_Press_6 = 1; // 标记长按开始
if (Key_Up == 6)
{
if (Time_1s_6 >= 1000)
my_data2 += 5; // 长按松手+5
else
my_data2++; // 短按+1
Long_Press_6 = 0; // 长按结束
Time_1s_6 = 0; // 重置时间
}
定时器支持(Timer1中断)
void Timer1_Isr(void) interrupt 3
{
// S5长按计时
if (Long_Press_5)
{
if (++Time_1s_5 >= 1000)
Time_1s_5 = 1001; // 卡死时间,防止溢出
}
else
Time_1s_5 = 0; // 清零
// S6长按计时
if (Long_Press_6)
{
if (++Time_1s_6 >= 1000)
Time_1s_6 = 1001; // 卡死时间
}
else
Time_1s_6 = 0; // 清零
}
考点解析
考点1:模式切换
unsigned char Seg_show_mode; // 0-温度显示 1-参数设置 2-DAC输出
void Key_Proc()
{
// ...(三行消抖代码)
if (Key_Down == 4)
{
// 循环切换0→1→2→0...
// 0%3=0, 1%3=1, 2%3=2, 3%3=0
Seg_show_mode = (++Seg_show_mode) % 3;
}
}
考点2: 参数保存与验证
unsigned char Tmax_Control, Tmin_Control; // 参数设置值
unsigned char Tmax, Tmin; // 参数保存值
void Key_Proc()
{
// ...(三行消抖代码)
if (Key_Down == 8)
Tmax_Control++;
if (Key_Down == 9)
Tmin_Control++;
// 按下S4确认输入
if (Key_Down == 4)
{
if (Tmax_Control >= Tmin_Control) // 条件验证
{
Tmax = Tmax_Control; // 保存有效值
Tmin = Tmin_Control;
}
else // 不满足条件
{
Tmax_Control = Tmax; // 恢复原值
Tmin_Control = Tmin;
}
}
}
关键要点总结
DS18B20要点:
- 读取顺序 :先低8位,后高8位
- 通信时序 :严格遵守写时序和读时序
- 总线释放 :
DQ = 1是释放总线,让设备控制
按键系统要点:
- 三行消抖 :
Key_Down = Key_Val & (Key_Old ^ Key_Val) - 长按检测 :需要定时器配合计时
- 模式切换 :使用取余运算实现循环切换
- 参数限制 :设置上下限防止越界
编程技巧:
- 状态保存 :使用
Key_Old保存上一次状态 - 条件验证 :保存前验证参数有效性
- 时间卡死 :防止计时器溢出
- 中断利用 :将时间敏感任务放入定时器中断
