STM32F03 与 ESP-8266-01 之间的 UART 通信

UART Communication Between STM32F03 and ESP-8266-01

我正在尝试让智能手机应用程序与 MCU (STM32F030R8) 进行通信。我目前正在进行的步骤是让 WiFi 模块与 MCU 通信。在使用 Arduino Uno/PC 终端时,我可以使用 AT 固件配置 ESP,但实际上我想通过 STM 板做同样的事情。

当我将代码加载到 STM 并使用 Tera Term 将数据发送到 STM 时,它应该能够将 AT 命令发送到 ESP,但它不起作用。现在我不知道为什么这不起作用。我正在寻找有关我可能错过的代码或我 overlooked/am 不知道的其他原则的指示。

过去几天我在互联网上四处搜索,但没有找到太多有用的东西。这实际上是我使用 C 的经验总和。感谢您的帮助!

硬件设置如下...

STM32     ESP
PA10      TX
PA9       RX
3.3V      VCC
3.3V      CH_PD
GND       GND

UNO       ESP
TX        TX
RX        RX
3.3V      VCC
3.3V      CH_PD
GND       GND

我把科学怪人放在一起的代码如下。我正在使用 Keil uVision 5.

#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>

void USART1_Init(void);
void USART2_Init(void);
void USART1_Write(char ch[]);
char USART1_Read(void);

int main(void)
{
    // disable the interrupt detection
    __disable_irq();

    RCC->AHBENR |= 0x00020000;                      // enable port A clock
    GPIOA->MODER |= 0x00000400;                     // set mode for PA5

    USART1_Init();
    USART2_Init();

    char strCommand[50];

    NVIC_EnableIRQ(USART1_IRQn);
    __enable_irq();

    printf("\r\nInterface for ESP8266 AT commands.\r\n");
    printf("Please enter the AT command: ");
    gets(strCommand);
    USART1_Write(strCommand);
    printf("\r\n");

    while (1);
}

// write data to the peripheral via USART1
void USART1_Write(char ch[])
{
    // wait while the tx buffer is empty
    while (!(USART1->ISR & 0x00000080));
    for (int i = 0; i < strlen(ch); i++)
    {
        USART1->TDR = (ch[i] & 0xFF);
    }
    USART1->TDR = 0x0000000D;
    USART1->TDR = 0x0000000A;
}

// read data from the peripheral via USART1
char USART1_Read(void)
{
    // wait while the rx buffer is empty
    while (USART1->ISR & 0x00000020);
    return USART1->RDR;
}

// write data to the PC via USART2
int USART2_Write(int ch)
{
    // wait while the tx buffer is empty
    while (!(USART2->ISR & 0x00000080));
    USART2->TDR = (ch & 0xFF);
    return ch;
}

// read data from the PC via USART2
int USART2_Read(void)
{
    // wait while the rx buffer is empty
    while (!(USART2->ISR & 0x00000020));
    return USART2->RDR;
}

// initialize USART1
void USART1_Init(void)
{
    RCC->APB2ENR |= 0x00004000;                 // enable USART1 clock

    GPIOA->AFR[1] |= 0x00000110;                // set AF1 to PA9, PA10

    GPIOA->MODER |= 0x00280000;                 // define GPIO modes to alternate function for PA9, PA10

    USART1->BRR = 0x00000341;                   // set the baud rate, 9600 @ 8MHz

    USART1->CR1 = 0x0000002C;                   // enable te, re, and rx interrupt
    USART1->CR1 |= 0x00000001;                  // enable ue
}

// initialize USART2
void USART2_Init(void)
{
    RCC->APB1ENR |= 0x00020000;                 // enable USART2 clock

    GPIOA->AFR[0] |= 0x00001100;                // set AF1 to PA2, PA3

    GPIOA->MODER |= 0x000000A0;                 // define GPIO modes to alternate function for PA2, PA3

    USART2->BRR = 0x00000341;                   // set the baud rate, 9600 @ 8MHz

    USART2->CR1 = 0x0000000C;                   // enable te and re
    USART2->CR1 |= 0x00000001;                  // enable ue
}

// handle the USART1 interrupt event
void USART1_IRQHandler(void)
{
    char c;
    if (USART1->ISR & 0x00000020)
    {
        c = USART1->RDR;
        //GPIOA->ODR ^= 0x00000020;             // toggle the PA5 state
        printf("%c", c);
    }
}

// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};

int fgetc(FILE *f)
{
    int c;

    c = USART2_Read();

    if (c == '\r')
    {
        USART2_Write(c);
        c = '\n';
    }
    USART2_Write(c);

    return c;
}

int fputc(int c, FILE *f)
{
    return USART2_Write(c);
}

编辑:

我稍微修改了代码并继续尝试。当尝试更改广播网络 name/password(它没有用)时,它现在会一致地回复命令中的前两个键入的字符,并在片刻之后发出乱码,看起来它应该被召唤"AT+GMR" 命令。以下代码是上传到设备的代码。关于这怎么可能发生的任何想法?谢谢!

#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>

void USART1_Init(void);
void USART2_Init(void);
void USART1_Write(char ch[]);
char USART1_Read(void);

int main(void)
{
    // disable the interrupt detection
    __disable_irq();

    RCC->AHBENR |= 0x00020000;                      // enable port A clock
    GPIOA->MODER |= 0x00000400;                     // set mode for PA5

    USART1_Init();
    USART2_Init();

    char strCommand[50];

    NVIC_EnableIRQ(USART1_IRQn);
    __enable_irq();

    printf("\r\nInterface for ESP8266 AT commands.\r\n");
    printf("Please enter the AT command: ");
    gets(strCommand);
    USART1_Write(strCommand);
    printf("\r\n");

    while (1);
}

// write data to the peripheral via USART1
void USART1_Write(char ch[])
{
    // wait for the tx buffer to be empty
    while (!(USART1->ISR & 0x00000080));
    for (int i = 0; i < strlen(ch); i++)
    {
        USART1->TDR = (ch[i] & 0xFF);
    }
//  USART1->TDR = '\r';
//  USART1->TDR = '\n';
}

// read data from the peripheral via USART1
char USART1_Read(void)
{
    // wait while the rx buffer is empty
    while (USART1->ISR & 0x00000020);
    return USART1->RDR;
}

// write data to the PC via USART2
int USART2_Write(int ch)
{
    // wait while the tx buffer is empty
    while (!(USART2->ISR & 0x00000080));
    USART2->TDR = (ch & 0xFF);
    return ch;
}

// read data from the PC via USART2
int USART2_Read(void)
{
    // wait while the rx buffer is empty
    while (!(USART2->ISR & 0x00000020));
    return USART2->RDR;
}

// initialize USART1
void USART1_Init(void)
{
    RCC->APB2ENR |= 0x00004000;                 // enable USART1 clock

    GPIOA->AFR[1] |= 0x00000110;                // set AF1 to PA9, PA10

    GPIOA->MODER |= 0x00280000;                 // define GPIO modes to alternate function for PA9, PA10

    USART1->BRR = 0x00000341;                       // set the baud rate, 9600 @ 8MHz

    USART1->CR1 = 0x0000002C;                       // enable te, re, and rx interrupt
    USART1->CR1 |= 0x00000001;                  // enable ue
}

// initialize USART2
void USART2_Init(void)
{
    RCC->APB1ENR |= 0x00020000;                 // enable USART2 clock

    GPIOA->AFR[0] |= 0x00001100;                // set AF1 to PA2, PA3

    GPIOA->MODER |= 0x000000A0;                 // define GPIO modes to alternate function for PA2, PA3

    USART2->BRR = 0x00000341;                       // set the baud rate, 9600 @ 8MHz

    USART2->CR1 = 0x0000000C;                       // enable te and re
    USART2->CR1 |= 0x00000001;                  // enable ue
}

// handle the USART1 interrupt event
void USART1_IRQHandler(void)
{
    char c;
    while (1)
    {
        if (USART1->ISR & 0x00000020)
        {
            c = USART1->RDR;
        }
        else
        {
            break;
        }
        printf("%c", c);
    }
}

// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};

int fgetc(FILE *f)
{
    int c;

    c = USART2_Read();

    if (c == '\r')
    {
        USART2_Write(c);
        c = '\n';
    }
    USART2_Write(c);

    return c;
}

int fputc(int c, FILE *f)
{
    return USART2_Write(c);
}

我能够使用以下代码让 ESP 响应 AT 命令。有些部分被注释掉了,因为我只是在科学怪人地编写 'working' 代码。我能够通过硬编码字符串更改 SSID 和密码。我只是通过按 'Enter' 来发送它来让代码继续。

事实证明,问题出在向 ESP 发送数据(而不是接收,这是我最初的理论)。现在我需要获取代码以从终端接收 uint8_t[],但这是与原始问题不同的问题,因此我将其标记为已回答。

感谢@hamboy75、@Juraj 和@KamilCuk 的帮助!

#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>

void USART1_Init(void);
void USART2_Init(void);
void USART1_Write(char ch[]);
char USART1_Read(void);
void USART1_Get(unsigned char *string);

void USART1_PutChar(uint8_t ch);
void USART1_Write2(uint8_t *str);

int main(void)
{
    // disable the interrupt detection
    __disable_irq();

    RCC->AHBENR |= 0x00020000;                      // enable port A clock
    GPIOA->MODER |= 0x00000400;                     // set mode for PA5

    USART1_Init();
    USART2_Init();

    char strCommand[50];
    uint8_t str[] = "AT+CWSAP_CUR=\"tempNetwork\",\"tempPassword\",1,2,1,0\r\n";

    NVIC_EnableIRQ(USART1_IRQn);
    __enable_irq();

    printf("\r\nInterface for ESP8266 AT commands.\r\n");
    printf("Please enter the AT command: ");
    gets(strCommand);
    //USART1_Write(strCommand);
    USART1_Write2(str);
    printf("\r\n");

    while (1);
}

// write data to the peripheral via USART1
void USART1_Write(char ch[])
{
    // wait for the tx buffer to be empty
    while (!(USART1->ISR & 0x00000080));
    for (int i = 0; i < strlen(ch); i++)
    {
        //USART1->TDR = (ch[i] & 0xFF);
    }
    //USART1->TDR = '\r';
    //USART1->TDR = '\n';

    USART1->TDR = ('T' & 0xFF);
    USART1->TDR = ('T' & 0xFF);
    USART1->TDR = '\r';
    USART1->TDR = '\n';
}

// write a string via USART1
void USART1_Write2(uint8_t *str)
{
    while (*str != 0)
    {
        USART1_PutChar(*str);
        str++;
    }
}

// write one character via USART1
void USART1_PutChar(uint8_t ch)
{
    while (!(USART1->ISR & 0x00000080));
    USART1->TDR = ch;
}

// read data from the peripheral via USART1
char USART1_Read(void)
{
    // wait while the rx buffer is empty
    while (USART1->ISR & 0x00000020);
    return USART1->RDR;
}

// write data to the PC via USART2
int USART2_Write(int ch)
{
    // wait while the tx buffer is empty
    while (!(USART2->ISR & 0x00000080));
    USART2->TDR = (ch & 0xFF);
    return ch;
}

// read data from the PC via USART2
int USART2_Read(void)
{
    // wait while the rx buffer is empty
    while (!(USART2->ISR & 0x00000020));
    return USART2->RDR;
}

// initialize USART1
void USART1_Init(void)
{
    RCC->APB2ENR |= 0x00004000;                 // enable USART1 clock

    GPIOA->AFR[1] |= 0x00000110;                // set AF1 to PA9, PA10

    GPIOA->MODER |= 0x00280000;                 // define GPIO modes to alternate function for PA9, PA10

    USART1->BRR = 0x00000341;                       // set the baud rate, 9600 @ 8MHz

    USART1->CR1 = 0x0000002C;                       // enable te, re, and rx interrupt
    USART1->CR1 |= 0x00000001;                  // enable ue
}

// initialize USART2
void USART2_Init(void)
{
    RCC->APB1ENR |= 0x00020000;                 // enable USART2 clock

    GPIOA->AFR[0] |= 0x00001100;                // set AF1 to PA2, PA3

    GPIOA->MODER |= 0x000000A0;                 // define GPIO modes to alternate function for PA2, PA3

    USART2->BRR = 0x00000341;                       // set the baud rate, 9600 @ 8MHz

    USART2->CR1 = 0x0000000C;                       // enable te and re
    USART2->CR1 |= 0x00000001;                  // enable ue
}

// handle the USART1 interrupt event
void USART1_IRQHandler(void)
{
    char c;
    while (1)
    {
        if (USART1->ISR & 0x00000020)
        {
            c = USART1->RDR;
            printf("%c", c);
        }
        else
        {
            break;
        }
    }
}

// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};

int fgetc(FILE *f)
{
    int c;

    c = USART2_Read();

    if (c == '\r')
    {
        USART2_Write(c);
        c = '\n';
    }
    USART2_Write(c);

    return c;
}

int fputc(int c, FILE *f)
{
    return USART2_Write(c);
}