stm32中DS18B20程序设计
时间: 2023-09-13 18:10:00 浏览: 224
DS18B20是一种数字温度传感器,可以通过一根单总线线路进行通信。在STM32中使用DS18B20需要先了解其通信协议,然后编写对应的程序。
DS18B20通信协议基于1-Wire总线,需要使用STM32的GPIO来模拟1-Wire总线。具体的通信流程如下:
1. 发送复位信号(reset):主机(STM32)拉低总线,持续时间大于480us,然后释放总线,等待DS18B20拉低总线表示接收到复位信号。
2. 发送指令(command):主机发送指令(例如读取温度),指令由8位二进制数据组成,每一位都要在60us内完成发送和接收。
3. DS18B20响应:DS18B20在接收到指令后,会发送响应信号(response),拉低总线15-60us,然后释放总线。
4. 数据传输:主机发送和接收数据,数据由8位二进制数据组成,每一位都要在60us内完成发送和接收。
5. 延时:在每一步操作后,需要等待一定的时间,从而等待DS18B20完成相应的操作。
下面是一个简单的STM32程序,用于读取DS18B20的温度:
```c
#include "stm32f10x.h"
#define DS18B20_GPIO GPIOA
#define DS18B20_PIN GPIO_Pin_1
void delay_us(uint16_t us)
{
uint16_t i;
while(us--)
{
i = 10; // 这里的延时是根据CPU的主频来计算的,需要根据实际情况进行调整
while(i--);
}
}
void ds18b20_reset(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(500);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(100);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
while(GPIO_ReadInputDataBit(DS18B20_GPIO, DS18B20_PIN) == Bit_RESET);
while(GPIO_ReadInputDataBit(DS18B20_GPIO, DS18B20_PIN) == Bit_SET);
}
void ds18b20_write_byte(uint8_t byte)
{
uint8_t i;
for(i = 0; i < 8; i++)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN);
if(byte & (1 << i))
{
delay_us(5);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(80);
}
else
{
delay_us(80);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(5);
}
}
}
uint8_t ds18b20_read_byte(void)
{
uint8_t i, byte = 0;
for(i = 0; i < 8; i++)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(2);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
if(GPIO_ReadInputDataBit(DS18B20_GPIO, DS18B20_PIN) == Bit_SET)
{
byte |= (1 << i);
}
delay_us(60);
}
return byte;
}
float ds18b20_read_temperature(void)
{
uint8_t temp_l, temp_h;
float temp;
ds18b20_reset();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0x44);
delay_us(750);
ds18b20_reset();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0xbe);
temp_l = ds18b20_read_byte();
temp_h = ds18b20_read_byte();
temp = (temp_h << 8) | temp_l;
temp = temp * 0.0625;
return temp;
}
int main(void)
{
float temperature;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
while(1)
{
temperature = ds18b20_read_temperature();
// 这里可以将温度值通过串口或LCD等方式显示出来
}
}
```
在这个程序中,ds18b20_reset()函数用于发送复位信号,ds18b20_write_byte()函数用于发送指令和数据,ds18b20_read_byte()函数用于接收数据,ds18b20_read_temperature()函数用于读取DS18B20的温度。在主函数中,不断读取温度并将其显示出来。
需要注意的是,这个程序中的延时函数是通过循环来实现的,需要根据实际情况进行调整。另外,DS18B20的通信速度较慢,每次读取温度需要耗费一定的时间,因此需要考虑如何优化程序性能。
阅读全文