stm32串口驱动和esp8266的使用

这篇具有很好参考价值的文章主要介绍了stm32串口驱动和esp8266的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

本文并不对相关知识进行讲解,只是这次的实验课要实现的任务有些复杂,我也踩了一些坑,对代码实现思路进行复现和记录,并不是技术科普性文章,基础知识还是要自己有所掌握。


1.stm32的串口通讯
  • 开发板:stm32f407zgt6课程学习板
  • 下载器:j-link

串口通信是单片机一种基础的通信协议,对时序要求比较严格,一般都是通过硬件实现。stm32初始化串口通讯:

首先查看原理图type-b接口对应的单片机引脚(这一步老师初始化里已经配置好:
type-b的接口连线
stm32 esp8266,stm32,单片机,嵌入式硬件

跳帽连线,可以看到需要将uart3 tx/rx的引脚通过跳帽选择连接到单片机
stm32 esp8266,stm32,单片机,嵌入式硬件

对应单片机的引脚:为tx-pc10 rx-pc11
stm32 esp8266,stm32,单片机,嵌入式硬件

之后我们就可以通过库函数对应配置

void UART3_Configuration(void)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    USART_InitTypeDef   USART_InitStructure;
    //  开启GPIO_D的时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    //  开启串口3的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//复用推挽输出
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
	//串口对应设置
    USART_InitStructure.USART_BaudRate   = 115200;//波特率
    //波特率是一个知识点,可能之后考试会考(确信)
    //不使用校验位,所以是八位
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits   = USART_StopBits_1;//停止位
    //不使用校验位
    USART_InitStructure.USART_Parity     = USART_Parity_No;
    //流控信号选择
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	//发送和接收同时使用过
    USART_InitStructure.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART3, &USART_InitStructure);
        //接收中断使能,可以跳转到函数定义的头文件看第二个参数的作用
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
    /* Enable the USARTx Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
	/* 使能串口3 */
    USART_Cmd(USART3, ENABLE);
}

配置好串口,相当于我们把消息通讯的机器组装好,接下来就要进行发送和接收消息的配置。

发送函数:

void USART3_Senddata(unsigned char *Data, unsigned int length)
{
    while(length--)
    {
        USART_SendData(USART3,*Data++);
        while (USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET);
    }
}

这里USART_SendData是标准库提供的函数,发送一个字节,硬件在发送数据时,发送状态会进行标志位置位,我们只需要进行判断读取是否发送完成再进行下一个字节的发送就好了,所以这里用while()循环一下。

printf的重定向:这里有一个小应用是关于c语言中printf函数的使用,看到这里想必大家都会明白,数据传输的底层就是对每一个字节的传输,如果我们只是对字符char的传输,那么一个字节就可以实现很好通讯,但是如果我们想对整数和浮点数进行信息传递,那么势必要从他们的存储方式进行转换,这是很麻烦的一件事。那么我们就会想到c语言里好像无所不能打印的printf,如果我们能直接使用他不就能解决大部分事情了。所以很多单片机的示例代码里都会对printf进行重定向配合串口实现和上位机的通讯,以便于方便的对单片机进行debug。而printf的底层就是调用fputc对文件写下一个字符。因此我们可以看到以下代码:

int fputc(int ch, FILE *f)
{
    USART3->SR;              // 防止复位后无法打印首字符
    USART_SendData(USART3, (u8) ch);
    while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);

    return (ch);
}

这样我们就可以使用printf和电脑进行通讯了。
进行初步尝试,查看是否配置正确。

int main()
{
    SysTick_Init();
    UART3_Configuration();
	printf("hello world\n");
	while(1){
	
	}
}

下载程序,把使用type-b线连接电脑和板子,打开上位机连接显示ch340对应的com口。按下复位键,看到上位机接收到hello world,表示成功。(记得将跳帽插到232的那一侧)。
stm32 esp8266,stm32,单片机,嵌入式硬件
stm32 esp8266,stm32,单片机,嵌入式硬件
以上是发送
同时还有接收部分

可以在接收startup_stm32f4xx.s文件中找到USART3_IRQHandler中断函数

void USART3_IRQHandler(void)
{
    if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)                //  判断中断标志位
    {
        USART_ClearITPendingBit(USART3, USART_IT_RXNE);
        USART_ReceiveData(USART3);  //把发来的消息接收一下
        printf("123");
    }
}

再次连接单片机和电脑,使用上位机向单片机发送消息,得到以下现象:
stm32 esp8266,stm32,单片机,嵌入式硬件

说明接收中断配置成功。

2.esp8266

在配置好串口之后,对于与单片机进行串口通讯的其他外设,就只需要进行发送和接收消息的处理了。

初始化

看看wifi模块对应的引脚
stm32 esp8266,stm32,单片机,嵌入式硬件

可以看到这里使用的是uart5串口,对应的单片机引脚是rx-pd2,tx-pc12。我们只需要对上面的usart3对应的初始化函数进行修改,就可以配置成功,这里不在赘述,值得一提的是,uart5资源在stm32f4中只有异步串口功能,因此在英文组成上是uart而非usart。
uart5的配置:

void UART5_Configuration(unsigned int baud)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    USART_InitTypeDef   USART_InitStructure;
    NVIC_InitTypeDef    NVIC_InitStructure;
    Uart5.ReceiveFinish = 0;
    Uart5.RXlenth = 0;
    Uart5.Time = 0;
    Uart5.Rxbuf = Uart5ReceiveBuf;
    //  开启GPIOA的时钟  
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOC, ENABLE);
    //  开启串口1的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);
  
    USART_InitStructure.USART_BaudRate   = baud;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits   = USART_StopBits_1;
    USART_InitStructure.USART_Parity     = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode       = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(UART5, &USART_InitStructure);
    /* 使能串口1 */   /* Enable the USARTx Interrupt */
    USART_Cmd(UART5, ENABLE);
    USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
    
    /* NVIC configuration */
    NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    USART_Cmd(UART5, ENABLE);
}

void UART5_Senddata(unsigned char *Data, unsigned int length)
{
    while(length--)
    {
        USART_SendData(UART5,*Data++);
        while (USART_GetFlagStatus(UART5, USART_FLAG_TC)==RESET);
    }
}
与esp8288进行通讯

大家在做这块实验的时候,最多的是不知道模块是否正确的工作了,只看手机有没有搜到热点,如果没有又不知道哪里出现了问题,手足无措。我们可以在网上搜以下这个模块的使用方法,看一些特性,可以让我们更好的进行调试。
对于esp8266,它具有回显功能,即他接收到消息就会将消息原封不动的返回,并且返回对应的应答。利用这个我们可以看到我们的消息发送和接收是否正常。因此我们首先要处理从模块中接收的应答消息,并且如果能把他想办法打印出来,不就可以看到哪里出现了问题。

首先定义一个接收消息的结构体。然后在接收中断里使用。

struct UsartData                                          
{      
    unsigned char *Rxbuf;
    unsigned int   RXlenth;
    unsigned char  Time;
    unsigned char  ReceiveFinish;
};
USARTDATA   Uart5;
void UART5_IRQHandler(void)
{
    if (USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)         
    {
        USART_ClearITPendingBit(UART5, USART_IT_RXNE);
        Uart5.Rxbuf[Uart5.RXlenth++] = USART_ReceiveData(UART5);
        Uart5.Time = 5; //表示正在接收
    }
}

然后在系统滴答定时器里发送这个接受的数据到uart3

void SysTick_Handler(void)
{    
    if (Uart5.Time > 0)
    {
        Uart5.Time--;
        if (Uart5.Time == 0)
        {
            Uart5.ReceiveFinish = 1;
            USART3_Senddata(Uart5.Rxbuf, Uart5.RXlenth);
            Uart5.RXlenth = 0;
        }
    }
}

然后我们就可以在主函数里对模块发消息进行控制。

在烧录初始化模块的代码之后要重新上电,否则模块不会发送消息,很奇怪
先发个“AT”看看是否有响应

int main(void)
{
    unsigned char test[11] = "WIFI test\r\n";
    SysTick_Init();             //  系统滴答定时器初始化
    // LEDGpio_Init();
    // KEYGpio_Init();
    UART3_Configuration();                                              //  USART3配置
    UART5_Configuration(115200);
    printf("hello world\n");
  
    UART5_Senddata("AT\r\n",4);
    delay_ms(5);
    //WIFI_Configuration();  
    while (1)
    {

    }
}
发送的消息不完整

发现他有反应,虽然但是很奇怪,我们明明发的“AT”,他却只给我们回了一个“T”,这个不知道问题出在哪里,我试了很多方法,但是每次初始化完成之后的第一条语句之后都是这样,会丢到一个字母。

    UART5_Senddata("AT\r\n",4);
    delay_ms(5);
    UART5_Senddata("AT\r\n",4);
    delay_ms(5);

所以我们把这句话发两次,再看
stm32 esp8266,stm32,单片机,嵌入式硬件

发现第二句话反应就正常了

配置wifi名和密码消息接收不全

然后我们再配置wifi名和密码

unsigned char CWSAP[38]     = "AT+CWSAP=\"Ctrl\",\"0123456789\",5,3\r\n";
UART5_Senddata(CWSAP,sizeof(CWSAP));
delay_ms(5);

stm32 esp8266,stm32,单片机,嵌入式硬件

这里他虽然接收到了消息并且回了ok,但是他回显有缺失,虽然不太明白为什么,但是只要把这句话的发送位置放在配置消息第一个,回显就会正常,而且正常配置密码的命令是后面跟的命令是5,3 改掉之后重新上电就会看到有密码的wifi了。

回显busy的问题

大家也看到了我在每次发送消息之间都会延时5ms,这是因为虽然你发送指令是按照一句一句发的,但是他本质还是在连续的发送char,每个语句之后模块会进行响应的设置,无法快速的接收下一条指令。

其实到这里我们的模块就已经调通了,之后只需要根据任务手册做下去实验就已经能够完成。


还有一些值得说的东西。

esp8266是现在很火的带wifi的mcu,性价比很高成本也很低,感兴趣的话可以学习一下他的at指令。

打算从他开始,入手以下esp32家族,最近势头很猛的国产32位单片机,在生态活跃上和物联网方面都势头很猛。文章来源地址https://www.toymoban.com/news/detail-792604.html

到了这里,关于stm32串口驱动和esp8266的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32串口驱动和esp8266的使用

    写在前面 本文并不对相关知识进行讲解,只是这次的实验课要实现的任务有些复杂,我也踩了一些坑,对代码实现思路进行复现和记录,并不是技术科普性文章,基础知识还是要自己有所掌握。 1.stm32的串口通讯 开发板:stm32f407zgt6课程学习板 下载器:j-link 串口通信是单片机

    2024年01月16日
    浏览(45)
  • 单片机设计_室内环境智能监测系统(STM32 OLED ESP8266 DHT11 MQ-2 加湿器)

    想要更多项目私wo!!! 室内环境智能监测系统 主要功能:         1.检测空气温湿度         2.检测光照强度         3.检测烟雾浓度         4.数据显示在手机端和设备OLED屏幕上         5.当空气温度高于设定的阈值时,风扇开启         6.当空气湿度低于

    2024年02月09日
    浏览(69)
  • K_A23_001 基于STM32等单片机AT指令驱动ESP-01/ESP-01S实现手机遥控点灯

    其他资料目录 直戳跳转 单片机型号 测试条件 模块名称 代码功能 STC89C52RC 晶振11.0592M ESP-01/ESP-01S模块 STC89C52RC驱动ESP-01/ESP-01S模块 实现手机遥控点灯 STM32F103C8T6(标准库) 晶振8M/系统时钟72M ESP-01/ESP-01S模块 STM32F103C8T6驱动ESP-01/ESP-01S模块 实现手机遥控点灯 ESP-01/ESP-01S模块 引脚

    2024年01月21日
    浏览(41)
  • K_A16_001 基于STM32等单片机驱动HX711称重模块 串口与OLED0.96双显示

    单片机型号 测试条件 模块名称 代码功能 STC89C52RC 晶振11.0592M HX711称重模块 STC89C52RC驱动HX711称重模块 串口与OLED0.96双显示 STM32F103C8T6 晶振8M/系统时钟72M HX711称重模块 STM32F103C8T6驱动HX711称重模块参数 串口与OLED0.96双显示 其他资料目录 直戳跳转 HX711参数 1.两路可选择差分输入

    2023年04月27日
    浏览(68)
  • K_A12_033 基于STM32等单片机驱动TCS34725颜色传感 串口与OLED0.96双显示

    单片机型号 测试条件 模块名称 代码功能 STC89C52RC 晶振11.0592M TCS34725颜色传感 模块 STC89C52RC驱动TCS34725颜色传感模块串口与OLED0.96双显示 STM32F103C8T6 晶振8M/系统时钟72M TCS34725颜色传感模块 STM32F103C8T6驱动TCS34725颜色传感模块串口与OLED0.96双显示 其他资料目录 直戳跳转 工作电压:

    2024年02月06日
    浏览(52)
  • K_A37_005 基于STM32等单片机驱动ADS1115 ADC模块 串口与OLED0.96双显示

    其他资料目录 直戳跳转 单片机型号 测试条件 模块名称 代码功能 STC89C52RC 晶振11.0592M ADS1115 ADC模块 STC89C52RC驱动ADS1115 ADC模块 串口与OLED0.96双显示 STM32F103C8T6 晶振8M/系统时钟72M ADS1115 ADC模块 STM32F103C8T6驱动ADS1115 ADC模块 串口与OLED0.96双显示 ADS1115 ADC模块 引脚说明 VIN 正极 5V供电

    2024年02月16日
    浏览(58)
  • 使用DMA传输实现单片机高效串口转发——以STM32系列为例

    Date Author Version Note 2023.08.06 Dog Tao V1.0 1. 完成了文档的撰写。 2023.08.23 Dog Tao V1.1 1. 增加了STM32F103-USART2的DMA传输配置示例。 2. 增加了STM32F103与F407单片机的DMA控制器介绍并更改了第一章节的结构。 应用场景 在许多现实应用场景中,例如工业自动化控制、嵌入式通信设备等领域,

    2024年02月14日
    浏览(53)
  • esp32单片机在arduino环境下,串口接收解码

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 当主控芯片发送一串数据,但此数据为一串字符串,需要将此字符串翻译成整型数组,以形成指令,控制串口屏。 例如:esp32单

    2024年02月09日
    浏览(46)
  • K_A18_008 基于STM32等单片机驱动SGP30气体传感器串口与OLED0.96双显示

    其他资料目录 直戳跳转 单片机型号 测试条件 模块名称 代码功能 STC89C52RC 晶振11.0592M SGP30气体传感器 模块 STC89C52RC驱动SGP30气体传感器模块串口与OLED0.96双显示 STM32F103C8T6 晶振8M/系统时钟72M SGP30气体传感器模块 STM32F103C8T6驱动SGP30气体传感器模块串口与OLED0.96双显示 SGP30气体传

    2024年02月04日
    浏览(57)
  • K_A12_022 基于STM32等单片机驱动VL53L0X模块 串口与OLED0.96双显示

    注:偏差校准步骤(均十六进制发送) 1、偏差校准命令 A5 21 0A D0(此处是在10CM处校准) 2、加载数据命令 A5 43 04 EC(断电重启后加载偏差补偿) 3、保存设置命令 A5 87 01 2D(保存设置后生效) 单片机型号 测试条件 模块名称 代码功能 STC89C52RC 晶振11.0592M VL53L0X模块 STC89C52RC驱动VL53L0X模

    2024年02月13日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包