GPIO 开漏输出的时候,也可以读取外部的数据
今天的实验是,能不能设置好引脚之后,这个引脚既能输出,又能输入呢?比如DHT11的数据引脚
1.按键的引脚设置为开漏输出,cpu能读取到正确的按键动作
查询方式和中断方式都可以正常工作(按键连接地,按下时是低电平)
但是有个非常重要的问题一定要注意,该引脚连接的外部设备在cpu输出高电平的时候是不是需要比较大的电流
2.接下来,我们做一下DHT11的实验,也能获得成功,读取位数据的时候,没有修改io端口的模式
实验代码如下:
#include <stm32f4xx.h>
#include "delay.h"
//华清远见stm32开发板,DHT11数据引脚连接的是PA3引脚
//初始化函数
//主要是引脚的配置
void DHT11_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义一个结构体,并且配置内容,GPIO_Init会根据这个结构体的内容配置我的io端口
//1.GPIO端口时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //之后操作任何外部设备,都要使能时钟
//2.配置io端口输出模式(PA3)
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //模式,输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 ; //哪一个或者哪几个 0x100 | 0x200 = 0x300
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; //输出速度
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉下拉是否需要
GPIO_Init(GPIOA, &GPIO_InitStruct);
//引脚默认输出高电平
GPIO_SetBits(GPIOA, GPIO_Pin_3);
}
uint8_t DHT11_start(void)
{
uint8_t cnt = 0;
//发送起始信号
GPIO_ResetBits(GPIOA, GPIO_Pin_3); //低电平 18ms
delay_ms(18);
GPIO_SetBits(GPIOA, GPIO_Pin_3); //高电平 20-40us
delay_us(30); //中间值 30us
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == Bit_SET) //等待DHT11响应,拉低电平
cnt = 0;
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == Bit_RESET)
{
cnt ++;
if(cnt > 100)
{
return 1; //出错,DHT11没有响应
}
delay_us(1);
}
cnt = 0;
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == Bit_SET) //拉高 80us
{
cnt ++;
if(cnt > 100)
{
return 1; //出错,DHT11没有响应
}
delay_us(1);
}
return 0;
}
static uint8_t read_bit(void)
{
uint8_t cnt = 0; //大约
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == Bit_RESET); //等待低电平变高
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == Bit_SET) //拉高 80us
{
cnt ++; //大约延时40us
if(cnt > 2)
{
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == Bit_SET); //等待高电平变低
return 1;
}
delay_us(20);
}
return 0;
}
uint8_t DHT11_Read_Byte(void)
{
uint8_t dat = 0;
uint8_t i;
for(i=0;i<8;i++)
{
dat <<= 1 ; //因为最后一位不需要左移,
dat |= read_bit();
}
return dat;
}
uint8_t DHT11_Read_Data(uint8_t *tmp,uint8_t *humi)
{
uint8_t recv;
uint8_t buf[5];
uint8_t i;
recv = DHT11_start(); //发送起始信号
if(recv == 1) //出错了
{
return 1;
}
for(i=0;i<5;i++)
{
buf[i] = DHT11_Read_Byte();
}
if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4])
{
*tmp = buf[2];
*humi = buf[0];
return 0;
}
return 1; //出错
}