Experimento del puerto serie STM32, desde la entrada hasta el abandono.

Experimento de puerto serie STM32


prefacio

Este artículo hace referencia a publicaciones de blog en Internet y las resume para ayudar a los novatos desde que comienzan hasta que se dan por vencidos .


Recordatorio: El siguiente es el texto principal de este artículo.

1. Puerto serie

¿Qué es un puerto serie?

El concepto de Comunicaciones Serial es muy simple, el puerto serial envía y recibe bytes bit a bit . Aunque son más lentos que la comunicación paralela byte a byte, los puertos seriales pueden usar un cable para enviar datos al mismo tiempo que otro cable para recibir datos. Es simple y permite la comunicación a larga distancia. Por ejemplo, cuando IEEE488 define el estado de tráfico paralelo, se estipula que la longitud total de la línea del dispositivo no debe exceder los 20 metros, y la longitud entre dos dispositivos no debe exceder los 2 metros; para los puertos seriales, la longitud puede alcanzar los 1200 metros Normalmente, los puertos serie se utilizan para la transmisión de caracteres ASCII. La comunicación se realiza mediante 3 cables, que son tierra, envío y recepción. Debido a que la comunicación en serie es asíncrona, el puerto puede enviar datos por un cable mientras recibe datos por el otro. Se utilizan otras líneas para el apretón de manos, pero no son necesarias. Los parámetros más importantes de la comunicación en serie son la velocidad en baudios, los bits de datos, los bits de parada y la paridad. Para la comunicación de dos puertos, estos parámetros deben coincidir.

La comunicación serial se divide en comunicación paralela y comunicación serial .

comunicación paralela

La comunicación en paralelo suele utilizar varias líneas de datos para transmitir bytes de datos al mismo tiempo, como se muestra en la Figura 11.1.
inserte la descripción de la imagen aquí

La salida de datos de 8 bits del dispositivo emisor se envía al dispositivo receptor al mismo tiempo de forma paralela. Las dos líneas inferiores sirven como consulta y respuesta, respectivamente. La consulta envía un mensaje al dispositivo receptor al enviar datos y pregunta si el dispositivo receptor está listo. Si el dispositivo receptor devuelve un mensaje diciendo que está listo, entonces el dispositivo emisor envía los datos de 8 bits. Este es el flujo de trabajo de la comunicación paralela.

Las características de la comunicación paralela: los bytes de datos se transmiten simultáneamente con varias líneas, la velocidad de transmisión es rápida y la tasa de información es alta. Sin embargo, se utilizan muchas líneas de transmisión y el costo es alto durante la transmisión a larga distancia.

comunicación kushiyuki

La comunicación en serie consiste en dividir los bytes de datos en bits y transmitirlos uno por uno en una línea de transmisión, como se muestra en la Figura 11.2.
inserte la descripción de la imagen aquí

La transmisión comienza desde el orden bajo. La primera transmisión es el orden bajo D0, luego D1, D2, hasta D7. Después de recopilar todos los bits recibidos, se restaura a un byte. Este método de transmisión es la comunicación en serie.

Las características de la comunicación en serie: se utilizan menos líneas de transmisión, el cableado es relativamente simple, el costo de la comunicación a larga distancia es menor y la velocidad no es tan rápida como la comunicación en paralelo.

La comunicación serial (según la dirección de la transferencia de datos) también se puede clasificar en: simplex , half-duplex y full- duplex ;

dirección de transferencia de datos concepto
símplex La transmisión de datos solo admite la transmisión de datos en una dirección y no se puede revertir. Es un poco similar a la señal de circuito cerrado en el televisor, solo se encarga de transmitir la señal al televisor.
medio duplex Permite la transferencia de datos en ambas direcciones. Sin embargo, en cierto punto, los datos solo pueden viajar en una dirección, y en realidad es una comunicación simplex que cambia de dirección; no requiere receptores y remitentes separados, los dos pueden combinarse para usar un solo puerto. Muchos walkie-talkies ahora usan esta forma de trabajar.
duplex completo Permite transferir datos en ambas direcciones al mismo tiempo . Por lo tanto, la comunicación full-duplex es una combinación de dos modos de comunicación simplex, que requieren receptores y transmisores independientes . Dale me gusta a nuestro teléfono ahora. Se puede hablar y contestar al mismo tiempo.

inserte la descripción de la imagen aquí

La comunicación serial (según el método de comunicación) también se puede clasificar en: comunicación asíncrona y comunicación síncrona .

forma de comunicación concepto
Comunicación asíncrona La comunicación asíncrona significa que el intervalo de tiempo entre dos caracteres (8 bits) en la comunicación no es fijo, mientras que el intervalo de tiempo de cada bit en un carácter es fijo y se transmite sin una señal de sincronización de reloj . Por ejemplo: UART (Universal Asynchronous Receiver/Transmitter), bus único.
comunicación sincrónica Es una tecnología de comunicación bit síncrona, que requiere que el emisor y el receptor tengan una señal de reloj síncrona de la misma frecuencia y fase , solo es necesario agregar un carácter de sincronización específico al frente del mensaje transmitido para establecer la sincronización entre el emisor Y el receptor, y luego controlar el reloj de sincronización.La siguiente transmisión/recepción bit a bit. Por ejemplo: interfaz de comunicación SPI, IIC.

inserte la descripción de la imagen aquí
En la comunicación asincrónica, la señal del reloj no se utiliza para la sincronización de datos. Insertan directamente algunos bits de señal para la sincronización en la señal de datos, o empaquetan los datos del sujeto y transmiten los datos en el formato de marco de datos. En la comunicación, ambas partes también deben acordar la velocidad de transmisión de datos (es decir, la velocidad en baudios), etc., para sincronizar mejor. Las velocidades de transmisión comúnmente utilizadas son 4800 bps, 9600 bps, 115200 bps, etc.
La imagen de arriba muestra la comunicación asincrónica y la imagen de abajo muestra la comunicación sincrónica.
inserte la descripción de la imagen aquí
En la comunicación sincrónica, se utilizará una línea de señal sobre el dispositivo transceptor para transmitir señales, y los dos lados coordinarán y sincronizarán los datos impulsados ​​por la señal del reloj. Por ejemplo, en la comunicación, ambas partes suelen estipular uniformemente muestrear la línea de datos en el flanco ascendente o descendente de la señal del reloj. La mayor parte del contenido transmitido por la señal de datos son datos válidos, y la comunicación asíncrona contendrá varios identificadores de la trama de datos, por lo que la eficiencia de la comunicación síncrona es alta, pero el error permisible de los relojes de ambas partes en la comunicación síncrona es pequeño. y un ligero error de reloj puede ocurrir.Los datos son caóticos, y el error permitido de los relojes de ambas partes en la comunicación asíncrona es relativamente grande.
No entraré en detalles sobre las cosas anteriores, y los amigos interesados ​​​​pueden aprender sobre ellas.

Interfaces de comunicación serie comunes

Interfaz de comunicación serie alfiler forma de comunicación Dirección de comunicación
UART TXD, RXD, TIERRA Comunicación asíncrona duplex completo
SPI SCK, MISO, MOSI comunicación sincrónica duplex completo
I2C SK, SDA: entrada/salida comunicación sincrónica medio duplex
solo autobús DQ: Enviar/Recibir Comunicación asíncrona medio duplex

En segundo lugar, base de comunicación en serie STM32

UART y USART

Hay dos interfaces de comunicación en serie de STM32, a saber: UART (receptor/transmisor asíncrono universal) y USART (receptor/transmisor asíncrono síncrono universal) . Para los chips de la serie STM32F10x de gran capacidad, hay 3 USART y 2 UART respectivamente.

Método de conexión de pines UART

inserte la descripción de la imagen aquí
RXD: pin de entrada de datos, aceptación de datos; TXD: pin de transmisión de datos, transmisión de datos.
Para la conexión entre los dos chips, la GND de los dos chips es un terreno común, y el TXD y el RXD están interconectados. La conexión cruzada aquí significa que el RxD del chip 1 está conectado al TXD del chip 2, y el RXD del chip 2 está conectado al TXD del chip 1. De esta manera, se puede realizar una comunicación de nivel TTL entre los dos chips.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Las principales características de USART
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Hablaremos de estas explicaciones aquí. Ahora para comenzar nuestro experimento, el código sigue al átomo puntual.

3. Parte experimental

Procedimiento experimental


1. Activación del reloj del puerto serie, activación del reloj GPIO
2. Restablecimiento del puerto serie
3. Configuración del modo del puerto GPIO
4. Inicialización del parámetro del puerto serie
5. Activación de la interrupción e inicialización de NVIC (este paso es necesario si se requiere la interrupción)
6. Activación del puerto serie
7 Escribir un manejador de interrupciones


1. El reloj del puerto serie está habilitado. El puerto serie es un periférico montado bajo APB2, por lo que la función de habilitación es:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1)

2. Restablecimiento del puerto serie. Cuando ocurre una anomalía en un dispositivo periférico, la configuración de restablecimiento del dispositivo periférico se puede usar para realizar el restablecimiento del dispositivo periférico, y luego el dispositivo periférico se puede reconfigurar para lograr el propósito de que funcione nuevamente. Generalmente, cuando el sistema configura por primera vez un periférico, primero realizará la operación de restablecer el periférico. El reinicio se realiza en la función USART_DeInit():

//void USART_DeInit(USART_TypeDef* USARTx);串口复位
USART_DeInit(USART1); //复位串口 1

3. Inicialización de parámetros del puerto serie. La inicialización del puerto serie se logra a través de la función USART_Init(),

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)

El primer parámetro de entrada de esta función es la etiqueta del puerto serial que especifica la inicialización, aquí se selecciona USART1.
El segundo parámetro de entrada es un puntero de estructura de tipo USART_InitTypeDef.Las variables miembro de este puntero de estructura se utilizan para configurar algunos parámetros del puerto serie. El formato general de implementación es:

USART_InitStructure.USART_BaudRate = bound; //波特率设置;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为 8 位数据格式
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_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口

Del formato de inicialización anterior, se puede ver que los parámetros que se configurarán para la inicialización son: velocidad en baudios, longitud de palabra, bit de parada, bit de paridad, control de flujo de datos de hardware, modo (recepción, envío). Podemos establecer estos parámetros según sea necesario.

4. Transmisión y recepción de datos. La transmisión y recepción de STM32 se realizan a través del registro de datos USART_DR, que es un registro doble que contiene TDR y RDR. Al escribir datos en este registro, el puerto serie los enviará automáticamente y, cuando se reciban datos, también se almacenarán en este registro.
Las funciones de la función de biblioteca STM32 para operar el registro USART_DR para enviar y recibir datos son:

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

5. Estado del puerto serie. El estado del puerto serie se puede leer a través del registro de estado USART_SR. Las descripciones de USART_SR se muestran en la Figura 9.1.1:
inserte la descripción de la imagen aquí
RXNE (el registro de datos de lectura no está vacío), cuando este bit se establece en 1, significa que los datos se han recibido y se pueden leer. En este momento, lo que debemos hacer es leer USART_DR tan pronto como sea posible Al leer USART_DR, este bit se puede borrar, o se puede escribir 0 en este bit para borrarlo directamente.

TC (transmisión completa), cuando se establece este bit, indica que se han enviado los datos en USART_DR. Se generará una interrupción si se establece este bit. También hay dos formas de borrar este bit: 1) Leer USART_SR y escribir USART_DR. 2) Escriba 0 directamente en este bit.

No explicaremos demasiado sobre los otros bits del registro de estado aquí, puede consultar el manual de referencia chino si lo necesita.
En nuestra función de biblioteca de firmware, la función para leer el estado del puerto serie es:

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)

El segundo parámetro de entrada de esta función es muy crítico, indica qué estado del puerto serie queremos ver, como RXNE (el registro de datos de lectura no está vacío) y TC (transmisión completa) explicados anteriormente. Por ejemplo, si queremos determinar si el registro de lectura no está vacío (RXNE), el método de operación de la función de biblioteca es:

USART_GetFlagStatus(USART1, USART_FLAG_RXNE);

Queremos juzgar si la transmisión está completa (TC), el método de operación de la función de biblioteca es:

USART_GetFlagStatus(USART1, USART_FLAG_TC);//这些标识号在 MDK 里面是通过宏定义定义的
#define USART_IT_PE ((uint16_t)0x0028)
#define USART_IT_TXE ((uint16_t)0x0727)
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_IT_RXNE ((uint16_t)0x0525)
#define USART_IT_IDLE ((uint16_t)0x0424)
#define USART_IT_LBD ((uint16_t)0x0846)
#define USART_IT_CTS ((uint16_t)0x096A)
#define USART_IT_ERR ((uint16_t)0x0060)
#define USART_IT_ORE ((uint16_t)0x0360)
#define USART_IT_NE ((uint16_t)0x0260)
#define USART_IT_FE ((uint16_t)0x0160)

6. Puerto serie habilitado. La habilitación del puerto serie se realiza mediante la función USART_Cmd(), que es fácil de entender. El método de uso
es:

USART_Cmd(USART1, ENABLE); //使能串口

7. Abra el puerto serie para responder a las interrupciones. A veces, cuando necesitamos habilitar la interrupción del puerto serie, también necesitamos habilitar la
interrupción del puerto serie.La función para habilitar la interrupción del puerto serie es:

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,
FunctionalState NewState)

El segundo parámetro de entrada de esta función es indicar el tipo de puerto serial habilitado, es decir, qué interrupción está habilitada, porque hay muchos tipos de interrupciones de puerto serial. Por ejemplo, cuando recibimos datos (el registro de datos de lectura RXNE no está vacío), queremos generar una interrupción, entonces nuestro método para abrir la interrupción es:

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断

Queremos generar una interrupción al final del envío de datos (TC, envío completado), entonces el método es:

USART_ITConfig(USART1, USART_IT_TC, ENABLE);

8. Obtenga el estado de interrupción correspondiente.
Cuando habilitamos una interrupción, cuando ocurre la interrupción, se establecerá un bit de bandera en el registro de estado . A menudo, en la función de manejo de interrupciones, para determinar qué tipo de interrupción es la interrupción, la función utilizada es:

ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)

Por ejemplo, si habilitamos la interrupción de finalización de transmisión del puerto serie, cuando ocurra la interrupción, podemos llamar a esta función en el controlador de interrupciones
para determinar si se trata de la interrupción de finalización de transmisión del puerto serie. El método es el siguiente:

USART_GetITStatus(USART1, USART_IT_TC)

El valor devuelto es SET, lo que indica que se produce la interrupción de la finalización de la transmisión del puerto serie.
A través de la explicación anterior, podemos lograr la configuración más básica del puerto serie. Para una introducción más detallada al puerto serie, consulte
las páginas 516 a 548 del "Manual de referencia STM32", el capítulo sobre Receptor asíncrono síncrono universal.

Echemos también un vistazo a la configuración de IO:
inserte la descripción de la imagen aquí

usart.c

//初始化 IO 串口 1
//bound:波特率
void uart_init(u32 bound)
{
    
    
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//①串口时钟使能, GPIO 时钟使能,复用时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|
RCC_APB2Periph_GPIOA, ENABLE); //使能 USART1,GPIOA 时钟
//②串口复位
USART_DeInit(USART1); //复位串口 1
//③GPIO 端口模式设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //ISART1_TX PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX PA.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10
//④串口参数初始化
USART_InitStructure.USART_BaudRate = bound; //波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为 8 位
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_Rx | USART_Mode_Tx;//收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
#if EN_USART1_RX //如果使能了接收
//⑤初始化 NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级 3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //中断优先级初始化
//⑤开启中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
#endif
//⑥使能串口
USART_Cmd(USART1, ENABLE); //使能串口
}

C Principal

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
int main(void)
{
    
    
	u8 t;
	u8 len;
	u16 times=0;
	delay_init(); //延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设 置 NVIC 中 断 分 组 2
	uart_init(115200); //串口初始化波特率为 115200
	LED_Init(); //LED 端口初始化
	KEY_Init(); //初始化与按键连接的硬件接口
	while(1)
	{
    
    
		if(USART_RX_STA&0x8000)
		{
    
     
			len=USART_RX_STA&0x3f; //得到此次接收到的数据长度
			printf("\r\n 您发送的消息为:\r\n\r\n");
			for(t=0;t<len;t++)
			{
    
    
				 USART_SendData(USART1, USART_RX_BUF[t]); //向串口 1 发送数据
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
			//等待发送结束
			}
			printf("\r\n\r\n"); //插入换行
			USART_RX_STA=0;
		}else
		{
    
     
			times++;
			if(times%5000==0)
			{
    
     
				printf("\r\n 战舰 STM32 开发板 串口实验\r\n");
				printf("正点原子@ALIENTEK\r\n\r\n");
			}
			if(times%200==0)printf("请输入数据,以回车键结束\n");
			if(times%30==0)LED0=!LED0; //闪烁 LED,提示系统正在运行.
			delay_ms(10);
		}
	}


Resumir

Eso es todo por el artículo de hoy. Si crees que está bien escribir, dale me gusta y síguenos. Si aún no lo entiende, haga clic en el enlace, el enlace de video de la estación Xiaopo va directamente

Supongo que te gusta

Origin blog.csdn.net/qq_42866708/article/details/113405124
Recomendado
Clasificación