msp430f149的数码管显示DS18B20 单线温度传感器的温度
时间: 2025-06-10 12:58:46 浏览: 20
### MSP430F149 配合 DS18B20 和数码管实现温度显示
以下是基于 MSP430F149 的 DS18B20 温度传感器读取并显示在数码管上的示例代码。此代码实现了单总线通信协议来获取 DS18B20 的温度数据,并通过简单的 I/O 控制驱动共阳极七段数码管。
#### 主要功能描述
- **DS18B20 数据采集**:利用 MSP430F149 的 GPIO 口模拟单总线协议,完成 DS18B20 初始化、ROM 命令发送以及温度寄存器读取。
- **数码管显示控制**:将读取到的温度值转换为 ASCII 字符串形式,在共阳极七段数码管上逐位动态扫描显示。
```c
#include <msp430.h>
#define DELAY_US(x) __delay_cycles((unsigned int)(x * (double)SystemCoreClock / 1e6))
// 定义端口配置
#define DQ_PIN BIT7 // P1.7 连接 DS18B20 单线接口
#define DIGITAL_PORT P1 // 数码管连接至其他 IO 端口
volatile unsigned char temperature; // 存储当前温度整数值
volatile float temp_float = 0.0f; // 浮点型存储温度值
void delay_ms(unsigned int ms); // 毫秒级延时函数声明
void one_wire_reset(); // DS18B20 复位检测子程序
void one_wire_write_byte(char byte_to_send); // 向 DS18B20 发送字节
char one_wire_read_byte(void); // 从 DS18B20 接收字节
float read_temperature_ds18b20(); // 获取 DS18B20 当前温度
void display_on_seven_segment(float value); // 显示浮点数于数码管
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗定时器
// 配置 P1.7 作为 DS18B20 输入/输出引脚
DIGITAL_PORT->DIR |= DQ_PIN;
DIGITAL_PORT->OUT &= ~DQ_PIN;
while(1){
temp_float = read_temperature_ds18b20();
display_on_seven_segment(temp_float);
delay_ms(500); // 刷新间隔时间
}
}
/**
* @brief 延时毫秒级别
*/
void delay_ms(unsigned int ms){
volatile unsigned long i, j;
for(i=ms;i>0;i--){
for(j=1200;j>0;j--){}; // 调整循环次数适配不同系统频率
}
}
/**
* @brief DS18B20 总线复位操作
*/
void one_wire_reset(){
DIGITAL_PORT->DIR |= DQ_PIN; // 设置为主动低电平模式
DIGITAL_PORT->OUT &= ~DQ_PIN; // 下拉信号线
DELAY_US(480); // 维持至少 480 微妙低电平
DIGITAL_PORT->DIR &= ~DQ_PIN; // 放开总线让其恢复高阻态
DELAY_US(70); // 等待主机释放后设备响应
}
/**
* @brief 向 DS18B20 写入一个字节的数据
*/
void one_wire_write_byte(char byte_to_send){
unsigned char bit_count;
for(bit_count=0;bit_count<8;bit_count++){
if(byte_to_send & 0x01){
DIGITAL_PORT->DIR &= ~DQ_PIN; // 如果是 '1',短暂下拉再放开
DELAY_US(2);
}else{ // 若写的是 '0'
DIGITAL_PORT->DIR |= DQ_PIN; // 强行拉低较长时间
DELAY_US(60);
}
DIGITAL_PORT->DIR &= ~DQ_PIN; // 上升沿结束该比特周期
DELAY_US(1);
byte_to_send >>= 1; // 移位处理下一个比特
}
}
/**
* @brief 从 DS18B20 中读取一字节数据
*/
char one_wire_read_byte(void){
unsigned char data_in=0, count_bit;
for(count_bit=0;count_bit<8;count_bit++){
DIGITAL_PORT->DIR |= DQ_PIN; // 开始采样之前先短促地下拉同步
DELAY_US(2);
DIGITAL_PORT->DIR &= ~DQ_PIN; // 松手等待器件回复
DELAY_US(12); // 让对方有足够的时间准备有效逻辑状态
if(DIGITAL_PORT->IN & DQ_PIN){
data_in |= 0x01 << (7-count_bit); // 将收到的一位拼接到变量高位处
}
}
return(data_in);
}
/**
* @brief 读取 DS18B20 返回的实际环境温度
*/
float read_temperature_ds18b20(){
short raw_temp_data_lsb,raw_temp_data_msb,temp_int_part;
float fractional_part;
one_wire_reset(); // 执行一次完整的初始化流程
one_wire_write_byte(0xCC); // 不带 ROM 地址跳过序列号匹配阶段
one_wire_write_byte(0x44); // 请求启动内部 A/D 转换过程
one_wire_reset(); // 准备好再次访问目标芯片
one_wire_write_byte(0xCC); // ...
one_wire_write_byte(0xBE); // 查询暂存区命令
raw_temp_data_lsb = one_wire_read_byte();// LSB 寄存器内容
raw_temp_data_msb = one_wire_read_byte();// MSB 寄存器内容
temp_int_part = ((short)((raw_temp_data_msb<<8)|raw_temp_data_lsb)) >> 4;// 提取出符号扩展后的整体部分
fractional_part = (((raw_temp_data_lsb)&0xF)*625)/10000.0f; // 解析小数精度成分
return(((temp_int_part)<0)?(-fractional_part):(fractional_part)+temp_int_part);
}
/**
* @brief 把指定浮点数值映射到多个七段显示器上面闪烁呈现出来
*/
void display_on_seven_segment(float value){
static const unsigned char seven_seg_map[]={
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
unsigned char integer_digits[4],i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
}
```
由于篇幅原因未完全展开 `display_on_seven_segment` 方法的具体实现细节,请补充完整以支持多位数字滚动刷新机制[^1]。
阅读全文
相关推荐














