39. DS18b20 功能扩展
- #include "pref.h"
- #include "digital_display.h"
- #include "timer.h"
- #include "ntc.h"
- #include "bee.h"
- #include <STDIO.H>
- #include "cmp.h"
- #include "internal_eeprom.h"
- #include "ds18b20.h"
-
- bit B_1ms; // 1ms标志
- u16 msecond;
-
- void sys_init();
- void init_usb();
-
- void main()
- {
- u16 temp;
- u8 digital_display_pos[8] = {DIS_BLACK, DIS_BLACK, DIS_BLACK, DIS_BLACK, DIS_BLACK, DIS_BLACK, DIS_BLACK, DIS_BLACK};
-
- u8 serial[8];
- u8 config[5];
-
- sys_init();
-
- init_time0();
- digital_display_init();
-
- init_usb();
-
- EA = 1; // 打开总中断
-
- ds18b20_read_serial(serial);
- ds18b20_read_cfg(serial, config);
-
- // 接收任意串口数据后继续执行, 方便调试
- while (!bUsbOutReady)
- ;
-
- printf_usb("\r\nserial: %X %X %X %X %X %X %X %X\r\n", serial[7], serial[6], serial[5], serial[4], serial[3], serial[2], serial[1], serial[0]);
- printf_usb("\r\nconfig: %X %X %X %X %X\r\n", config[4], config[3], config[2], config[1], config[0]);
-
- digital_display_black();
-
- // (12*32768*WDT_PS) / MAIN_Fosc
- // WDT_PS = 128
- // 24M 系统时钟,看门狗计数器溢出时间大概为 2秒
- WDT_CONTR = 0x26;
-
- while (1)
- {
- WDT_CONTR = 0x36;
-
- if (B_1ms)
- {
- B_1ms = 0;
- if (++msecond >= 500)
- {
- msecond = 0;
-
- temp = ds18b20_read_temperature_target(serial);
- printf_usb("%0.2f", ((float)temp / 100));
-
- if (ds18b20_is_minus())
- {
- if (temp > 999)
- {
- digital_display_pos[3] = DIS_;
- digital_display_pos[4] = temp / 1000;
- }
- else
- {
- digital_display_pos[3] = DIS_BLACK;
- digital_display_pos[4] = DIS_;
- }
- }
- else
- {
- digital_display_pos[3] = DIS_BLACK;
- if (temp > 999)
- {
- digital_display_pos[4] = temp / 1000;
- }
- else
- {
- digital_display_pos[4] = DIS_BLACK;
- }
- }
- digital_display_pos[5] = (temp % 1000) / 100 + DIS_DOT;
- digital_display_pos[6] = ((temp % 100) / 10);
- digital_display_pos[7] = temp % 10;
- digital_display_set_pos(
- digital_display_pos[0],
- digital_display_pos[1],
- digital_display_pos[2],
- digital_display_pos[3],
- digital_display_pos[4],
- digital_display_pos[5],
- digital_display_pos[6],
- digital_display_pos[7]);
- usb_OUT_done();
- }
-
- if (!P34)
- {
- // 精度切换
- delay_ms(100);
- if (!P34)
- {
- digital_display_set(12345678);
- temp = (config[2] & 0x60) >> 5;
- if (temp >= 3)
- {
- temp = 0;
- }
- else
- {
- temp++;
- }
- ds18b20_cfg_ratio(serial, temp);
- ds18b20_read_cfg(serial, config);
- printf_usb("\r\nconfig: %X %X %X %X %X\r\n", config[4], config[3], config[2], config[1], config[0]);
-
- while (!P34)
- {
- WDT_CONTR = 0x36;
- }
- digital_display_black();
- }
- }
- }
- }
- }
-
- void sys_init()
- {
- WTST = 0; // 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
- EAXFR = 1; // 扩展寄存器(XFR)访问使能
- CKCON = 0; // 提高访问XRAM速度
-
- {
- P0M1 = 0x30;
- P0M0 = 0x30; // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P1M1 = 0x30;
- P1M0 = 0x30; // 设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P2M1 = 0x3c;
- P2M0 = 0x3c; // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P3M1 = 0x50;
- P3M0 = 0x50; // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P4M1 = 0x3c;
- P4M0 = 0x3c; // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P5M1 = 0x0c;
- P5M0 = 0x0c; // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P6M1 = 0xff;
- P6M0 = 0xff; // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
-
- P7M1 = 0x00;
- P7M0 = 0x00; // 设置为准双向口
- }
- }
-
- void init_usb()
- {
- P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
- P3M1 |= 0x03; // 需要将 P30,P31 设置为高阻输入模式
-
- IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
- while (!(IRC48MCR & 0x01))
- ; // 等待震荡源稳定
-
- USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
- USBCON = 0x09; // 使能 USB 功能
-
- usb_init(); // 调用 USB CDC 初始化库函数
-
- EUSB = 1; // 使能 USB 中断
- }
-
- /********************** Timer0 1ms中断函数 ************************/
- void timer0(void) interrupt 1
- {
- B_1ms = 1; // 1ms标志
- DisplayScan(); // 1ms扫描显示一位
- bee_on_1ms();
- }
复制代码
- #include "ds18b20.h"
-
- sbit DQ = P3 ^ 3; // DS18B20的数据口
- bit _MinusFlag; // 负数标志,0:正数,1:负数
-
- bit ds18b20_is_minus()
- {
- return _MinusFlag;
- }
-
- void ds18b20_read_scratchpad(u8 *temperature, u8 *tHL, u8 *cfg, u8 *user, u8 *crc)
- {
- ds18b20_writebyte(0xBE); // 读取暂存器
-
- temperature[0] = ds18b20_readbyte(); // 读温度低字节
- temperature[1] = ds18b20_readbyte(); // 读温度高字节
-
- tHL[0] = ds18b20_readbyte(); // T_H Reg
- tHL[1] = ds18b20_readbyte(); // T_L Reg
-
- *cfg = ds18b20_readbyte(); // Config Reg
-
- ds18b20_readbyte(); // FFh
-
- user[0] = ds18b20_readbyte(); // User byte
- user[1] = ds18b20_readbyte(); // User byte
-
- *crc = ds18b20_readbyte();
- }
-
- void ds18b20_write_scratchpad(u8 *config)
- {
- ds18b20_writebyte(0x4E); // 写入暂存器
-
- ds18b20_writebyte(config[0]);
- ds18b20_writebyte(config[1]);
- ds18b20_writebyte(config[2]);
-
- ds18b20_reset();
- }
-
- void ds18b20_write_eeprom(u8 *serial)
- {
- ds18b20_reset();
- ds18b20_match_serial(serial);
- ds18b20_writebyte(0x48); // 写入EEPROM
- while (!DQ)
- ;
- }
-
- u16 ds18b20_read_tempturature()
- {
- u16 Temperature;
- u8 temp[2];
-
- ds18b20_read_scratchpad(temp, 0, 0, 0, 0);
-
- if (temp[1] & 0xf8) // 判断是否位负数
- {
- _MinusFlag = 1; // 设置负数标志
- Temperature = (temp[1] << 8) | temp[0];
- Temperature = ~Temperature + 1;
- Temperature *= 0.625; // 0.0625 * 10,保留1位小数点
- }
- else
- {
- _MinusFlag = 0; // 清除负数标志
- Temperature = (((temp[1] << 8) | temp[0]) * 6.25); // 0.0625 * 100,保留2位小数点
- }
-
- return Temperature;
- }
-
- void ds18b20_reset()
- {
- CY = 1;
- while (CY)
- {
- DQ = 0; // 送出低电平复位信号
- delay_us(240); // 延时至少480us
- delay_us(240);
- DQ = 1; // 释放数据线
- delay_us(60); // 等待60us
- CY = DQ; // 检测存在脉冲
- delay_us(240); // 等待设备释放数据线
- delay_us(180);
- }
- }
-
- void ds18b20_read_serial(u8 *dat)
- {
- u8 i, j, tmp_u8;
- bit tmp_bit;
-
- ds18b20_reset();
- ds18b20_writebyte(0xF0); // Search ROM
-
- for (i = 0; i < 8; i++)
- {
- tmp_u8 = 0;
- for (j = 0; j < 8; j++)
- {
- tmp_bit = ds18b20_readbit(); // B20 TX bit
- while (ds18b20_readbit() == tmp_bit) // B20 TX !bit
- ;
- ds18b20_writebit(tmp_bit); // Master TX bit
- // printf_usb("%d", tmp_bit);
- tmp_u8 >>= 1;
- if (tmp_bit)
- {
- tmp_u8 |= 0x80;
- }
- }
- *dat++ = tmp_u8;
- }
- }
-
- void ds18b20_match_serial(u8 *dat)
- {
- u8 i, j, tmp_u8;
-
- ds18b20_reset();
- ds18b20_writebyte(0x55); // Match ROM
-
- for (i = 0; i < 8; i++)
- {
- tmp_u8 = dat[i];
- for (j = 0; j < 8; j++)
- {
- ds18b20_writebit(tmp_u8 & 0x01); // Master TX bit
- tmp_u8 >>= 1;
- }
- }
- }
-
- void ds18b20_writebit(bit b)
- {
- DQ = 0; // 开始时间片
- delay_us(1); // 延时等待
- DQ = b;
- delay_us(60); // 等待时间片结束
- DQ = 1; // 恢复数据线
- delay_us(1); // 恢复延时
- }
-
- void ds18b20_writebyte(u8 dat)
- {
- char i;
-
- for (i = 0; i < 8; i++) // 8位计数器
- {
- DQ = 0; // 开始时间片
- delay_us(1); // 延时等待
- dat >>= 1; // 送出数据
- DQ = CY;
- delay_us(60); // 等待时间片结束
- DQ = 1; // 恢复数据线
- delay_us(1); // 恢复延时
- }
- }
-
- bit ds18b20_readbit()
- {
- bit i;
- DQ = 0; // 开始时间片
- delay_us(1); // 延时等待
- DQ = 1; // 准备接收
- delay_us(1); // 接收延时
- i = DQ;
- delay_us(60); // 等待时间片结束
- return i;
- }
-
- u8 ds18b20_readbyte()
- {
- u8 i;
- u8 dat = 0;
-
- for (i = 0; i < 8; i++) // 8位计数器
- {
- dat >>= 1;
- DQ = 0; // 开始时间片
- delay_us(1); // 延时等待
- DQ = 1; // 准备接收
- delay_us(1); // 接收延时
- if (DQ)
- dat |= 0x80; // 读取数据
- delay_us(60); // 等待时间片结束
- }
-
- return dat;
- }
-
- void ds18b20_read_cfg(u8 *serial, u8 *cfg)
- {
- u8 t_threshold[2], _user[2];
- u8 _config;
-
- ds18b20_reset();
- ds18b20_match_serial(serial);
- ds18b20_read_scratchpad(0, t_threshold, &_config, _user, 0);
-
- cfg[0] = t_threshold[0];
- cfg[1] = t_threshold[1];
- cfg[2] = _config;
- cfg[3] = _user[0];
- cfg[4] = _user[1];
- }
-
- /**
- * 0 - 0.5
- * 1 - 0.25
- * 2 - 0.125
- * 3 - 0.0625
- */
- void ds18b20_cfg_ratio(u8 *serial, u8 ratio)
- {
- u8 config[5];
- ds18b20_read_cfg(serial, config);
-
- config[2] = ratio << 5;
-
- ds18b20_reset();
- ds18b20_match_serial(serial);
- ds18b20_write_scratchpad(config);
- ds18b20_write_eeprom(serial);
- }
-
- u16 ds18b20_read_temperature_target(u8 *serial)
- {
- ds18b20_match_serial(serial); // 找指定设备
- ds18b20_writebyte(0x44); // 写入转换命令
- while (!DQ)
- ; // 等待转换完成
-
- ds18b20_reset(); // 复位
- ds18b20_match_serial(serial); // 找指定设备
- return ds18b20_read_tempturature();
- }
-
- u16 ds18b20_read_temperature_any()
- {
- ds18b20_reset(); // 设备复位
- ds18b20_writebyte(0xCC); // 跳过ROM命令
- ds18b20_writebyte(0x44); // 开始转换命令
- while (!DQ)
- ; // 等待转换完成
-
- ds18b20_reset(); // 设备复位
- ds18b20_writebyte(0xCC); // 跳过ROM命令
- return ds18b20_read_tempturature(); // 读暂存存储器命令
- }
复制代码
|