分析下代码#include "dht11.h" #include "delay.h" //复位DHT11 void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us } //等待DHT11的回应 //返回1:未检测到DHT11的存在 //返回0:存在 u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0; } //从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; } //从DHT11读取一个字节 //返回值:读到的数据 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat; } //从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } }else return 1; return 0; } //初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 u8 DHT11_Init(void) { RCC->APB2ENR|=1<<3; //使能PORTB口时钟 GPIOB->CRH&=0XFFFFFF0F;//PORTB9 推挽输出 GPIOB->CRH|=0X00000030; DHT11_Rst(); return DHT11_Check(); }
时间: 2024-04-26 12:20:33 浏览: 12
这段代码是用来驱动温湿度传感器DHT11的。具体来说,代码中的函数包括:
1. DHT11_Rst():复位DHT11,拉低DQ引脚至少18ms,然后拉高20~40us。
2. DHT11_Check():等待DHT11的回应,返回1表示未检测到DHT11的存在,返回0表示存在。
3. DHT11_Read_Bit():从DHT11读取一个位,等待DHT11引脚变为低电平,然后等待40us,读取引脚状态。
4. DHT11_Read_Byte():从DHT11读取一个字节,读取8位数据,返回读到的数据。
5. DHT11_Read_Data():从DHT11读取一次数据,读取40位数据,判断校验和是否正确,如果正确则将温度和湿度值存储在传入的参数中,返回0表示正常,返回1表示读取失败。
6. DHT11_Init():初始化DHT11的IO口DQ,同时检测DHT11的存在,返回1表示不存在,返回0表示存在。
代码中使用了延时函数delay_ms()和delay_us(),以及读写GPIO的操作,其中GPIOB的9号引脚被用作DQ引脚。
相关问题
uint8_t DHT11_Init (void){ //DHT11初始化 RCC_APB2PeriphClockCmd(DHT11_RCC,ENABLE); //开始DHT11的时钟 DHT11_RST(); //DHT11端口复位,发出起始信号 return DHT11_Check(); //等待DHT11回应 }改错
这段代码的错误在于没有定义 `DHT11_RST()` 和 `DHT11_Check()` 函数,这两个函数的实现也没有给出。另外,代码中的注释应该使用英文。修改后的代码应该如下所示:
```c
uint8_t DHT11_Init(void) {
RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE); // Enable clock for DHT11
DHT11_Reset(); // Reset DHT11 port and send start signal
return DHT11_Response(); // Wait for DHT11 response
}
```
其中,`DHT11_Reset()` 函数用于复位 DHT11 端口并发送起始信号,`DHT11_Response()` 函数用于等待 DHT11 的响应。具体实现需要根据硬件电路和 DHT11 协议来编写。
编写DHT11和OLED驱动代码
以下是DHT11和OLED驱动代码的示例:
DHT11驱动代码:
```c
#include <msp430.h>
#define DHT11_PIN BIT4
void DHT11_Start(void)
{
P4DIR |= DHT11_PIN; //设置P4.4为输出
P4OUT &= ~DHT11_PIN; //使P4.4输出低电平
__delay_cycles(18000); //延时18ms
P4OUT |= DHT11_PIN; //使P4.4输出高电平
__delay_cycles(40); //延时40us
P4DIR &= ~DHT11_PIN; //设置P4.4为输入
}
int DHT11_Check_Response(void)
{
int response = 0;
__delay_cycles(40); //延时40us
if(!(P4IN & DHT11_PIN)) //判断是否为低电平响应
{
__delay_cycles(80); //延时80us
if(P4IN & DHT11_PIN) //判断是否为高电平响应
{
response = 1;
}
}
while(P4IN & DHT11_PIN); //等待低电平结束
return response;
}
void DHT11_Read_Data(int *data, int pin)
{
int i, j = 0;
for(i=0; i<5; i++)
{
data[i] = 0;
}
DHT11_Start(); //发送开始信号
if(DHT11_Check_Response()) //等待响应
{
for(i=0; i<40; i++)
{
while(!(P4IN & DHT11_PIN)); //等待高电平开始位
__delay_cycles(30); //延时30us
if(P4IN & DHT11_PIN) //判断是否为高电平数据位
{
j |= (1<<(7-(i%8))); //将数据存入j中
}
if(i%8 == 7)
{
data[i/8] = j;
j = 0;
}
}
}
}
```
OLED驱动代码:
```c
#include <msp430.h>
#define OLED_SCL BIT7
#define OLED_SDA BIT6
#define OLED_RST BIT5
#define OLED_DC BIT4
void OLED_Write_Command(unsigned char command)
{
UCB1IFG &= ~UCRXIFG; //清除接收标志位
UCB1TXBUF = command; //写入命令
while(!(UCB1IFG & UCTXIFG)); //等待发送完成
}
void OLED_Write_Data(unsigned char data)
{
UCB1IFG &= ~UCRXIFG; //清除接收标志位
UCB1TXBUF = data; //写入数据
while(!(UCB1IFG & UCTXIFG)); //等待发送完成
}
void OLED_Init(void)
{
P4DIR |= OLED_RST; //设置P4.5为输出
P4OUT &= ~OLED_RST; //使P4.5输出低电平
__delay_cycles(20000); //延时20ms
P4OUT |= OLED_RST; //使P4.5输出高电平
__delay_cycles(20000); //延时20ms
UCB1CTLW0 |= UCSWRST; //软件复位UCB1模块
UCB1CTLW0 |= UCMST + UCMODE_3 + UCSYNC; //主模式,3线SPI,同步通信
UCB1CTLW0 |= UCSSEL_2; //时钟源选择SMCLK
UCB1BRW = 0x02; //时钟分频为SMCLK/2
UCB1CTLW0 &= ~UCSWRST; //释放UCB1模块
P4DIR |= OLED_SCL + OLED_SDA + OLED_DC; //设置OLED引脚为输出
OLED_Write_Command(0xAE); //关闭OLED显示
OLED_Write_Command(0xD5); //设置时钟分频因子
OLED_Write_Command(0x80); //时钟分频因子为80h
OLED_Write_Command(0xA8); //设置显示偏移
OLED_Write_Command(0x3F); //偏移量为3Fh
OLED_Write_Command(0xD3); //设置显示开始行
OLED_Write_Command(0x00); //开始行为0
OLED_Write_Command(0x40); //设置显示位置
OLED_Write_Command(0x8D); //设置电荷泵
OLED_Write_Command(0x14); //开启电荷泵
OLED_Write_Command(0x20); //设置内存地址模式
OLED_Write_Command(0x02); //地址模式为页寻址模式
OLED_Write_Command(0xA1); //设置段重定向
OLED_Write_Command(0xC8); //设置COM扫描方向
OLED_Write_Command(0xDA); //设置COM硬件引脚配置
OLED_Write_Command(0x12); //设置COM引脚配置
OLED_Write_Command(0x81); //设置对比度控制
OLED_Write_Command(0xCF); //对比度为CFh
OLED_Write_Command(0xD9); //设置预充电周期
OLED_Write_Command(0xF1); //预充电周期为F1h
OLED_Write_Command(0xDB); //设置VCOMH
OLED_Write_Command(0x40); //VCOMH为40h
OLED_Write_Command(0xA4); //关闭全局显示开启
OLED_Write_Command(0xA6); //设置正常显示模式
OLED_Write_Command(0xAF); //开启OLED显示
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_Write_Command(0xB0 + y); //设置页地址(0~7)
OLED_Write_Command(((x & 0xf0) >> 4) | 0x10); //设置高位列地址
OLED_Write_Command((x & 0x0f) | 0x01); //设置低位列地址
}
void OLED_ShowString(unsigned char x, unsigned char y, char *str)
{
unsigned char c = 0;
while(str[c] != '\0')
{
OLED_ShowChar(x, y, str[c]);
x += 8;
c++;
}
}
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr)
{
unsigned char c = 0, i = 0;
c = chr - 32;
if(x > 120)
{
x = 0;
y++;
}
OLED_Set_Pos(x, y);
for(i=0; i<8; i++)
{
OLED_Write_Data(OLED_ASCII[c][i]);
}
}
```
注:这里的OLED_ASCII数组为OLED显示的ASCII码对应点阵,需要根据具体OLED屏幕型号进行调整。