Связь UART между STM32F03 и ESP-8266-01 - PullRequest
1 голос
/ 04 февраля 2020

Я пытаюсь получить приложение для смартфона для связи с MCU (STM32F030R8). Шаг, на котором я сейчас нахожусь, - заставить модуль WiFi общаться с MCU. Я могу использовать прошивку AT для настройки ESP при использовании терминала Arduino Uno / P C, но по сути хочу сделать то же самое через плату STM.

Когда я загружаю код в STM и использую Tera Term для отправки данных в STM, он должен иметь возможность отправлять AT-команды в ESP, но он не работает. Сейчас я в недоумении, почему это не работает. Я ищу указатели на код, который я, вероятно, пропустил, или другие принципы, которые я пропустил / не знаю.

За последние пару дней я искал по inte rnet, и мало что мне помогло. Это фактически сумма моего опыта с 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);
}

РЕДАКТИРОВАТЬ:

Я немного изменил код и продолжал пытаться. При попытке изменить транслируемое сетевое имя / пароль (это не сработало) теперь он последовательно отвечает первыми двумя набранными символами в команде и через мгновение выдает гиббери sh, похоже, он должен был быть вызван команда "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);
}

Tera Term output window

1 Ответ

0 голосов
/ 05 февраля 2020

Мне удалось заставить ESP отвечать на AT-команды следующим кодом. Есть закомментированные разделы, так как я просто откровенничал о своем пути к «рабочему» коду. Я смог изменить SSID и пароль через жестко закодированную строку. Я просто отправил его, нажав «Enter», чтобы получить код для продолжения.

Как оказалось, проблема заключается в отправке данных в ESP (а не в получении, что было моей первоначальной теорией). Теперь мне нужно получить код для получения uint8_t[] из терминала, но это отдельная проблема от исходного вопроса, поэтому я отмечу это как ответ.

Спасибо @ hamboy75, @Juraj, и @KamilCuk за вашу помощь!

it works

#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);
}
...