寒假第九讲(DS18B20与按键)

DS18B20 温度传感器与按键系统笔记

:satellite_antenna: 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中断挂载的任务:

  1. 数码管扫描 :每1ms扫描一位
  2. 按键消抖 :每10ms读取一次按键状态
  3. LED PWM :每1ms比较一次
  4. 闪烁标志翻转 :每500ms翻转一次

:bullseye: 按键系统

第一章:按键系统基础

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. 保存当前状态

:pushpin: 按键应用实例

按键类型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;      // 重置时间
}

:alarm_clock: 定时器支持(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;  // 清零
}

:counterclockwise_arrows_button: 考点解析

考点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;
        }
    }
}

:memo: 关键要点总结

DS18B20要点:

  1. 读取顺序 :先低8位,后高8位
  2. 通信时序 :严格遵守写时序和读时序
  3. 总线释放DQ = 1 是释放总线,让设备控制

按键系统要点:

  1. 三行消抖Key_Down = Key_Val & (Key_Old ^ Key_Val)
  2. 长按检测 :需要定时器配合计时
  3. 模式切换 :使用取余运算实现循环切换
  4. 参数限制 :设置上下限防止越界

编程技巧:

  1. 状态保存 :使用Key_Old 保存上一次状态
  2. 条件验证 :保存前验证参数有效性
  3. 时间卡死 :防止计时器溢出
  4. 中断利用 :将时间敏感任务放入定时器中断