前面准备好资料包了,接下来借助这块开发板硬件资源,着手外设的驱动练习吧。至于环境的搭建,这里就不再啰嗦,安装好Keil与基于F103的pack支持包即可。
这里笔者采用的是基于V5.38版本的Keil,使用该版本直接编译SDK中的参考例程需要注意ARM交叉编译器的版本选择,工程默认打开是基于“Compiler Version 5”,需要手动更改为“compiler Version 6”,否则编译不了。
然后就是在这个版本中,即便勾选了"Browse Information",如果工程路径中有中文字符的存在,则还是不能“Go To Definition of 'XXX'”。
本节主要分享基于DS18B20的温度精准采集,我们知道DS18B20是美国DSLIAS公司推出的单总线数字温度传感器,具有微型化、低功耗、高性能、抗干扰能力强、易匹配处理器等优点。处理器与DS18B20通信只需要一根数据线即可,同时该数据线还可以向挂接的DS18B20供电。DS18B20内部自带A/D转换器,通过内部的温度采集、A/D转换等一系列过程,将温度值以规定的格式转换为数据并输出,用户可以通过一些简单的算法,将数据还原为温度值。其分辨率可以达到12位,满足一般情况下对温度采集的需要。与模拟温度传感器相比,DS18B20省去了信号调理、A/D转换等通道处理电路,从而使得系统线路简单,成本低廉。 DS18B20的性能指标:
① 电压范围:+3.0~+5.5V(可用数据线供电)
② 测温范围:-55℃~+125℃
③ 通过编程可实现9~12位的数字读数方式,测温分辨率可达0.0625℃
④ 可自设定非易失性的报警上下限值。
精英板上针对温湿度传感接入已经设计专门接口,即板上U4位置。
这里采用一个自购的小模块接入,借助其它废弃的元器件管脚,插入圆形的插座上,然后杜邦线引入。如果有单独的DS18B20元器件,则无需转接。我们知道DS18B20是一款l-wire总线接口的器件,即与外部的处理器通信只有一根线,因此,通信流程就显得稍微复杂,需要用MCU的I/O口软件模拟l-wire的时序。
然后再写驱动代码,部分参照如下:
static uint8_t ds18b20_read_bit(void)
{
uint8_t data = 0;
DS18B20_DQ_OUT(0);
delay_us(2);
DS18B20_DQ_OUT(1);
delay_us(12);
if (DS18B20_DQ_IN)
{
data = 1;
}
delay_us(50);
return data;
}
static uint8_t ds18b20_read_byte(void)
{
uint8_t i, b, data = 0;
for (i = 0; i < 8; i++)
{
b = ds18b20_read_bit();
data |= b << i;
}
return data;
}
static void ds18b20_write_byte(uint8_t data)
{
uint8_t j;
for (j = 1; j <= 8; j++)
{
if (data & 0x01)
{
DS18B20_DQ_OUT(0);
delay_us(2);
DS18B20_DQ_OUT(1);
delay_us(60);
}
else
{
DS18B20_DQ_OUT(0);
delay_us(60);
DS18B20_DQ_OUT(1);
delay_us(2);
}
data >>= 1;
}
}
static void ds18b20_start(void)
{
ds18b20_reset();
ds18b20_check();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0x44);
}
uint8_t ds18b20_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
DS18B20_DQ_GPIO_CLK_ENABLE();
gpio_init_struct.Pin = DS18B20_DQ_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS18B20_DQ_GPIO_PORT, &gpio_init_struct);
ds18b20_reset();
return ds18b20_check();
}
short ds18b20_get_temperature(void)
{
uint8_t flag = 1;
uint8_t TL, TH;
short temp;
ds18b20_start();
ds18b20_reset();
ds18b20_check();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0xbe);
TL = ds18b20_read_byte();
TH = ds18b20_read_byte();
if (TH > 7)
{
TH = ~TH;
TL = ~TL;
flag = 0;
}
temp = TH;
temp <<= 8;
temp += TL;
if (flag == 0)
{
temp = (double)(temp+1) * 0.625;
temp = -temp;
}
else
{
temp = (double)temp * 0.625;
}
return temp;
}
int main(void)
{
uint8_t t = 0;
float temp,float_num;
short temperature;
HAL_Init();
sys_stm32_clock_init(RCC_PLL_MUL9);
delay_init(72);
usart_init(115200);
led_init();
while (ds18b20_init())
{
printf("DS18B20 Init Error\r\n");
delay_ms(200);
}
printf("DS18B20 OK\r\n");
while (1)
{
if (t % 50 == 0)
{
temperature = ds18b20_get_temperature();
temp = (float)temperature * 0.0625;
if (temperature < 0)
{
printf("采集的温度为:-%.2f\r\n",temp);
}
printf("采集的温度为:%.2f\r\n",temp);
}
delay_ms(4);
t++;
if (t == 100)
{
t = 0;
LED0_TOGGLE();
}
}
}
编译完成后,接入JLink调试器,选择JLink调试下载方式,并勾选下载完成后自动重启复位,检查下载算法是否ok。
板上实物接线如下图所示:
连接DS18B20时千万要注意电源的正负极方向,连接后小模块的红色指示灯会被点亮,然后打开串口调试助手,波特率设置115200,打开串口,然后将手指紧贴DS18B20的元器件上,串口打印出的采集温度值则会随之改变。实测采集的温度比较稳定,干扰少,很精准。效果如底部视频所示:
采集效果
|