DAY6-串口通信,超声波传感器和DHT11

160 阅读2分钟

(2)查看CPU芯片手册

image-20220827214525002

image-20220827214540223

(3)串口编程的库函数实现

在工程中添加串口库函数源码

image-20220827214544713

1)开始GPIOA和USART1的时钟

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

2)初始化GPIO位复用功能,并映射到串口1

GPIO_Init(...);
​
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

3)初始化串口

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
参数:
    USARTx - 哪个串口
    USART_InitStruct - 串口初始化结构
    
typedef struct
{
  uint32_t USART_BaudRate;            /*!< 波特率 */uint16_t USART_WordLength;          /*!< 数据位长度 @ref USART_Word_Length */uint16_t USART_StopBits;            /*!< 停止位位数 @ref USART_Stop_Bits */uint16_t USART_Parity;              /*!< 校验方式 @ref USART_Parity */
 
  uint16_t USART_Mode;                /*!< 发送/接收模式 @ref USART_Mode */uint16_t USART_HardwareFlowControl; /*!< 硬件流控制 @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;    

4)使能串口

            USART_Cmd(USART1,ENABLE);        

5)数据的发送和接收

发送:

//轮询
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
//传入哪个串口和要发送的数据//每次发送之前要等待上一个数据发送完成
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
//传入哪个串口的什么标志,返回SET表示有该标志,返回RESET表示没有该标志
//USART_FLAG_TC - 发送完成标志

练习:

使用串口1实现字符串的发送

4.通过串口实现printf函数

stm32工程中可以直接使用C标准函数,其中printf函数没有完全实现,预留了一个后门fputc,我们可以通过实现fputc函数完成通过串口printf打印的功能。

fputc格式:

int fputc(int ch,FILE *f)
{
    //.....
}
//ARM开发板运行程序,如果主机运行了调试器,程序就会使用主机的输入输出设备
//这种方式叫半主机模式,printf要通过串口1输出,就要关闭半主机模式
#pragma import(__use_no_semihosting)struct __FILE{
    int handle;    
};
​
FILE __stdout;
​
//定义_sys_exit函数,避免使用半主机模式
void _sys_exit(int x)
{
    x = x;
}
​
//重定义fputc
int fputc(int ch,FILE *f)
{
    //发送
    USART_SendData(USART1,ch);
   //等待数据发送完成
    while(SET!=USART_GetFlagStatus(USART1,USART_FLAG_TC));
 
   return ch;
}

5.使用中断实现串口的接收

由于何时发送数据由CPU决定,所以不存在大量无效查询的情形,可以不使用中断,但是串口来的接收CPU无法决定何时有数据接收,此时需要使用中断来提高效率。

串口中断和定时器中断类似,需要配置中断开关和NVIC。

1.NVIC
    NVIC_Init(...);
2.使能串口接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  

在串口中断处理函数中完成数据的接收

void USART1_IRQHandler(void)
{
    //判断是否为接收中断 ----- USART_GetITStatus(USART1,USART_IT_RXNE)==SET
    //清除中断标志 ----- USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    //接收数据 ---- uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
}

练习:

为串口添加控制LED和读取MQ2状态的命令

十八.超声波模块

1.原理

超声波模块发出超声波信号,超声波遇到障碍会反弹,得到发送超声波和收到超声波的事件间隔就可以计算当前位置到障碍物的距离。

image-20220827214555217

模块说明书:

image-20220827214601337

image-20220827214605919

注意事项:

测量范围:2cm ~ 400cm
测量时间间隔 > 60ms
供电电压:5V

2.超声波模块和开发板的连接

image-20220827214610352

具体操作:

PE6配置成输出,测量时发送>10us的高电平
配置PA8为输入,计算收到的高电平时间

3.代码逻辑

(1)初始化

//PE6 ----- OUT(默认低电平)
//PA8 ----- IN
GPIO_Init(...);

(2)测距

PE6拉高
延时15us
PE6拉低
​
等待PA8变高
开始计时
等待PA8变低
结束计时
​
通过计时间隔计算距离

练习:

获取超声波距离,当距离小于50cm使用蜂鸣器报警,大于50cm解除报警

距离大于150cm D1亮 小于150cm D1灭

(3)延时计算高电平时间有一定的误差,如果需要更加精准可以选择使用定时器

逻辑:
    定时器周期>60ms,参考周期1us左右
    电平变高 ---------- 重置/启动定时器(重写计数器) ------ TIM_SetCounter
    电平变低 ---------- 读取/关闭定时器(读取计数器) ------ TIM_GetCounter

十九.温湿度传感器(DHT11)

1.原理图

DHT11使用单总线通信,使用一根数据线进行数据传输,再加上VCC,GND,闲置接口(NC),一共四根线。

image-20220827214616468

单总线连接到了PG9,外接上拉电阻

2.查看DHT11的说明手册了解其如何工作

image-20220827214625522

数据格式:

image-20220827214628759

基本时序:

image-20220827214632285

CPU发送起始信号 ===> 模块响应起始信号 ===> 模块发送温湿度数据

(1)CPU的起始信号和模块响应

(2)如何读出1位数据(区分0和1)

image-20220827214640433

作业:

使用串口命令读出超声波的距离