Aprendizaje de la función de biblioteca TM4C123 (3) --- interrupción del puerto serie

prefacio

(1) Antes de estudiar este artículo, es necesario estudiar los dos primeros artículos.
(2) Para leer este artículo, debe preparar un módulo TTL a USB.

Introducción a la función

ROM_GPIOPinConfigure()

Configure la función alternativa del pin GPIO. Debido a que es imposible que un pin tenga solo una función de entrada y salida, también puede usarse como un pin multiplexado. Entonces, esta función se usa para llamar a esta función cuando IO necesita usarse para otras funciones.

/****** 函数声明 ******/
//这个存放在ROM
void ROM_GPIOPinConfigure(uint32_t ui32PinConfig);
//这个是存放在flash
void GPIOPinConfigure(uint32_t ui32PinConfig);

/****** 函数介绍 ******/
/* 作用 : 配置GPIO引脚的复用功能。
 * 传入参数 : 参数在 pin_map.h 中选择,例如 GPIOPinConfigure(GPIO_PB0_U1RX);是把 PB0 复用为
U1RX
 * 返回参数 : 无
*/

ROM_GPIOPinTypeUART()

Configure los pines utilizados por el periférico UART.

/****** 函数声明 ******/
//这个存放在ROM
void ROM_GPIOPinTypeUART(uint32_t ui32Port,uint8_t ui8Pins);
//这个是存放在flash
void GPIOPinTypeUART(uint32_t ui32Port,uint8_t ui8Pins);

/****** 函数介绍 ******/
/* 作用 : 配置UART外设使用的引脚。
 * 传入参数 : 
     * ui32Port : GPIO口的基地地址,GPIO_PORTx_BASE,x可为A,B,C,D,E,F,G,H
     * ui8Pins : GPIO_PIN_X,x可为1,2,3,4,5,6,7
 * 返回参数 : 无
*/

ROM_UARTConfigSetExpClk()

(1) Establezca la configuración de UART.
(2) Es necesario tener en cuenta un punto aquí: la función UARTStdioConfig () también puede configurar el puerto serie, pero personalmente no recomiendo usar esta configuración. Porque después de configurar esta función, el valor predeterminado es usar datos de 8 bits, sin bit de paridad y 1 bit de parada. Aunque también nos configuramos así más adelante.
(3)La función UARTStdioConfig() tiene un punto muy importante. Si llama al puerto serie configurado por esta función, puede usar la función UARTprintf(), pero no puede usar la función UARTCharput(). La función configurada con UARTConfigSetExpClk() puede usar la función UARTCharput(). Sin embargo, la función UARTprintf() no se puede utilizar.
(4) UART printf () es una función pseudo printf (), el método de uso es consistente con la función printf (). Pero habrá dos problemas de esta manera:
<1> Si se llama a la función UARTprintf(), pero la MCU tiene múltiples puertos seriales abiertos al mismo tiempo, se requiere toda la salida. De esta forma, ¿a qué puerto serie corresponde la función UARTprintf()?
<2> Esta función no es flexible de usar. Por ejemplo, limitación del tipo de datos: la función UARTprintf solo admite tipos de datos limitados, como números enteros y de punto flotante. Si necesita generar otros tipos de datos, es posible que deba escribir la función de salida usted mismo. Limitaciones de formato: la función UART printf utiliza la sintaxis de cadena de formato printf estándar, pero no todas las opciones de cadena de formato printf son compatibles. Por ejemplo, no admite tipos como long y long double. Limitación del tamaño del búfer: la función UARTprintf utiliza un búfer estático interno para almacenar la cadena formateada, por lo que la longitud de la cadena de salida está limitada por el tamaño del búfer. La salida de cadenas más largas que el tamaño del búfer puede dar como resultado una salida incompleta o truncada.

/****** 函数声明 ******/
//这个存放在ROM
void ROM_UARTConfigSetExpClk(uint32_t ui32Base,uint32_t ui32UARTClk,uint32_t ui32Baud,uint32_t ui32Config);
//这个是存放在flash
void UARTConfigSetExpClk(uint32_t ui32Base,uint32_t ui32UARTClk,uint32_t ui32Baud,uint32_t ui32Config);

/****** 函数介绍 ******/
/* 作用 : 设置UART的配置。
 * 传入参数 : 
     * ui32Base : UART端口的基地址
     * ui32UARTClk : 提供给UART模块的时钟速率。
     * ui32Baud : 波特率
     * ui32Config : 可选参数如下:
         * 数据位 : UART_CONFIG_WLEN_8(8数据位),
                    UART_CONFIG_WLEN_7(7数据位),
                    UART_CONFIG_WLEN_6(6数据位),
                    UART_CONFIG_WLEN_5(5数据位)
         * 停止位 : UART_CONFIG_STOP_ONE(1停止位),
                    UART_CONFIG_STOP_TWO (2停止位)
         * 校验位 : UART_CONFIG_PAR_NONE(无校验位) ,
                    UART_CONFIG_PAR_EVEN(偶校验),
                    UART_CONFIG_PAR_ODD (奇校验),
                    UART_CONFIG_PAR_ONE (1校验),
                    UART_CONFIG_PAR_ZERO (0校验)
 * 返回参数 : 无
*/

ROM_UARTFIFODesactivar()

(1) Se utiliza para desactivar FIFO.
(2) FIFO es un registro. Los datos de comunicación en serie pueden utilizar FIFO como estación de transferencia. Cuando la CPU necesita enviar datos, los envía a FIFO a la vez y luego FIFO los maneja. Si se reciben los datos, también se reciben primero en el FIFO y luego la CPU los procesa. Los beneficios de hacer esto:
<1>Esto permite que el puerto serie procese varios caracteres al mismo tiempo sin esperar a que se procese cada carácter. Esto puede reducir el retraso de la comunicación en serie y mejorar la eficiencia de la comunicación.
<2> Permite que el puerto serie procese varios caracteres al mismo tiempo sin esperar a que se procese cada carácter. Esto puede reducir el retraso de la comunicación en serie y mejorar la eficiencia de la comunicación.
<3> Cuando el búfer FIFO está habilitado, los datos recibidos por el puerto serie se almacenarán en el búfer FIFO en lugar de transmitirse directamente al búfer de recepción. Esto reduce el número de interrupciones y, por tanto, mejora la capacidad de respuesta del sistema.(Nota: ¡Si hace esto, el rendimiento en tiempo real del puerto serie se reducirá considerablemente!)
(3)Como queremos que el puerto serie responda tan pronto como reciba datos, desactivamos el FIFO.

/****** 函数声明 ******/
//这个存放在ROM
void ROM_UARTFIFODisable(uint32_t ui32Base);
//这个是存放在flash
void ROM_UARTFIFODisable(uint32_t ui32Base);

/****** 函数介绍 ******/
/* 作用 : 用于禁用FIFO。
 * 传入参数 : 
     * ui32Base :要禁用FIFO的UART端口的基地址
 * 返回参数 : 无
*/

ROM_UARTIntEnable()

Habilite fuentes de interrupción UART individuales.

/****** 函数声明 ******/
//这个存放在ROM
void ROM_UARTIntEnable(uint32_t ui32Base,uint32_t ui32IntFlags);
//这个是存放在flash
void UARTIntEnable(uint32_t ui32Base,uint32_t ui32IntFlags);

/****** 函数介绍 ******/
/* 作用 : 用于禁用FIFO。
 * 传入参数 : 
     * ui32Base :UART端口的基地址
     * ui32IntFlags : UART_INT_9BIT(9位地址匹配中断),
                       UART_INT_OE(错误中断,接收到的数据中出现了错误的“停止位”),
                       UART_INT_BE(错误中断,数据接收器的缓冲区已满时,继续接收数据而导致之前接收到的数据被覆盖,从而引发中断),
                       UART_INT_PE(奇偶校验错误中断),
                       UART_INT_FE(帧错误中断),
                       UART_INT_RT(接收超时中断),
                       UART_INT_TX(发送中断),
                       UART_INT_RX(接收中断),
                       UART_INT_DSR(DSR中断),
                       UART_INT_DCD(DCD中断),
                       UART_INT_CTS(CTS中断),
                       UART_INT_RI(RI中断)
 * 返回参数 : 无
*/

Registro UARTInt()

(1) Registro de la función de interrupción UART
(2) Esta función ROM no parece tener

/****** 函数声明 ******/
//这个是存放在flash
void UARTIntRegister(uint32_t ui32Base, void (*pfnHandler)(void));

/****** 函数介绍 ******/
/* 作用 : UART中断函数注册
 * 传入参数 : 
     * ui32Base :UART端口的基地址
     * void (*pfnHandler)(void) : 串口中断函数名字,此函数无返回值,无传入值
 * 返回参数 : 无
*/

ROM_IntPrioritySet()

Establezca la prioridad de la interrupción.

/****** 函数声明 ******/
//这个存放在ROM
void ROM_IntPrioritySet(uint32_t ui32Interrupt,uint8_t ui8Priority);
//这个是存放在flash
void IntPrioritySet(uint32_t ui32Interrupt,uint8_t ui8Priority);

/****** 函数介绍 ******/
/* 作用 : 设置中断的优先级
 * 传入参数 : 
     * ui32Interrupt :指定所涉及的中断。在hw_ints.h中定义
     * ui8Priority : 中断优先级,当同时断言多个中断时,具有最高优先级的中断将在较低优先级的中断之前被处理。xxx0 0000,只看 xxx 前三位。比如0的优先级比0xE0高。
 * 返回参数 : 无
*/

reasignación de printf

(1) Porque a muchas personas les gusta usar printf para reasignar los datos de impresión. Así que aquí también doy una explicación sencilla. Pero la reasignación de printf solo puede asignar un puerto serie, pero tengo un plan a continuación, que permite que todos los puertos serie puedan realizar la reasignación de printf.
(2) Solo necesitamos cambiar x un poco. También es necesario abrir MicroLIB.

inserte la descripción de la imagen aquí

//重新映射printf函数到UARTx,x可为1,2,3,4,5,6,7
int fputc(int ch, FILE *f){
    
    UARTCharPut(UARTx_BASE,ch);	return (ch);}
int fgetc(FILE *f) {
    
    int ch=UARTCharGet(UARTx_BASE);	return (ch);}

printf("* 作者     : CSND 风正豪 \r\n");

Reasignación simultánea de múltiples puertos serie

Copie directamente las siguientes funciones, puede inicializar directamente varios puertos serie

/* 作用 : 用于多路串口重定义
 * 传入参数 : 
     baseAddress : 要打印的串口地址,UARTx_BASE,x可为0,1,2,3,4,5,6,7
     format : 需要打印的东西
     ... : 如果是打印字符,输入%c。有符号数字,%d。用法与printf一样
 * 返回值 : 无
*/
void UART_printf(uint32_t baseAddress, const char *format,...)
{
    
    
    uint32_t length;
    va_list args;
    uint32_t i;
    char TxBuffer[128] = {
    
    0};

    va_start(args, format);
    length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer), (char*)format, args);
    va_end(args);

    for(i = 0; i < length; i++)
		{
    
    
			 while(UARTBusy(baseAddress));
			 UARTCharPut(baseAddress,TxBuffer[i]);
		}
}

Práctico

#include "stdio.h"
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_gpio.h"
#include "hw_ints.h"
#include "debug.h"
#include "fpu.h"
#include "gpio.h"
#include "pin_map.h"
#include "rom.h"
#include "sysctl.h"
#include "uart.h"
#include "uartstdio.h"


#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
    
    
}
#endif


/*
*********************************************************************************************************
*	函 数 名: PrintfLogo
*	功能说明: 打印例程名称和例程发布日期, 接上串口线后,打开PC机的串口终端软件可以观察结果
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void PrintfLogo(void)
{
    
    
	printf("*************************************************************\n\r");
	printf("* %s\r\n", "串口0控制RGB例程");	/* 打印例程名称 */
	printf("* 发布日期 : %s\r\n", "2023年4月24日");	/* 打印例程日期 */
	printf("* 使用芯片 : TM4C123GH6PZI7\r\n");
	printf("* 作者     : CSND 风正豪 \r\n");
	printf("*************************************************************\n\r");
}
/* 作用 : 用于多路串口重定义
 * 传入参数 : 
     baseAddress : 要打印的串口地址,UARTx_BASE,x可为0,1,2,3,4,5,6,7
     format : 需要打印的东西
     ... : 如果是打印字符,输入%c。有符号数字,%d。用法与printf一样
 * 返回值 : 无
*/
void UART_printf(uint32_t baseAddress, const char *format,...)
{
    
    
    uint32_t length;
    va_list args;
    uint32_t i;
    char TxBuffer[128] = {
    
    0};

    va_start(args, format);
    length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer), (char*)format, args);
    va_end(args);

    for(i = 0; i < length; i++)
		{
    
    
			 while(UARTBusy(baseAddress));
			 UARTCharPut(baseAddress,TxBuffer[i]);
		}
}

//串口0的接收中断
static uint8_t ch;
void UART0_IRQHandler(void)
{
    
    		
	//获取中断标志 原始中断状态 屏蔽中断标志		
  uint32_t flag = UARTIntStatus(UART0_BASE,1);
	//清除中断标志			
  UARTIntClear(UART0_BASE,flag);
	//判断FIFO是否还有数据
  while(UARTCharsAvail(UART0_BASE))		
  {
    
    	
		//接收数据
		ch=UARTCharGet(UART0_BASE);
	}	
}

void ConfigureUART0(void)
{
    
     
		//使能UART使用的GPIO外设 
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
		//使能 UART0
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
		//配置UART模式的GPIO引脚
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
		//设置串口0,时钟源速率为系统时钟,波特率为9600,8数据位,1停止位,无校验位
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE));
		//禁用UART模块的FIFO缓冲区。减少串口接收的延迟,提高响应速度。
		UARTFIFODisable(UART0_BASE);
		//使能UART0接收中断	
		UARTIntEnable(UART0_BASE,UART_INT_RX);
		//UART0中断函数注册	
		UARTIntRegister(UART0_BASE,UART0_IRQHandler);
		//设置中断优先级
		ROM_IntPrioritySet(INT_UART0,0x60);
}

//重新映射printf函数到UART0
int fputc(int ch, FILE *f){
    
    UARTCharPut(UART0_BASE,ch);	return (ch);}
int fgetc(FILE *f) {
    
    int ch=UARTCharGet(UART0_BASE);	return (ch);}

void RGB_Init(void)
{
    
    
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);  //使能GPIOF外设	
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_5);//红色
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6);//绿色
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4);//蓝色
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);//置高位熄灭
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_5, GPIO_PIN_5);//置高位熄灭
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, GPIO_PIN_6);//置高位熄灭
}

int main(void)
{
    
    
		ROM_FPUEnable();//使能浮点单元。这个函数必须在执行任何硬件浮点运算之前被调用;如果不这样做,将导致NOCP使用错误。
		ROM_FPULazyStackingEnable();//浮点延迟堆栈,减少中断响应延迟 
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |SYSCTL_OSC_MAIN);//配置系统时钟,系统时钟频率400M/2/2.5=80M
		RGB_Init();
    ConfigureUART0();//初始化串口0
    PrintfLogo();//串口打印版本信息
    while(1)
    {
    
    
			if((int8_t)ch == 'a')
			{
    
    
				UARTprintf("Turn on the LED1\n"); //无法使用
				UART_printf(UART0_BASE,"%s\n","hello world");
				GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_5, !GPIO_PIN_5);//置低位点亮
				SysCtlDelay(SysCtlClockGet() / 10);    
				GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_5, GPIO_PIN_5);//置高位熄灭
				SysCtlDelay(SysCtlClockGet() / 10);
			}

			if((int8_t)ch == 'b')
			{
    
    
				UART_printf(UART0_BASE,"2+2=%d\n",4);
				GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, !GPIO_PIN_6);//置低位点亮
				SysCtlDelay(SysCtlClockGet() / 10);    
				GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, GPIO_PIN_6);//置高位熄灭
				SysCtlDelay(SysCtlClockGet() / 10);
			}
			if((int8_t)ch == 'c')
			{
    
    
				UART_printf(UART0_BASE,"2+2.0=%f\n",4.0);
				GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, !GPIO_PIN_4);//置低位点亮
				SysCtlDelay(SysCtlClockGet() / 10);      
				GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);//置高位熄灭
				SysCtlDelay(SysCtlClockGet() / 10);
			}
    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_63922192/article/details/132444689
Recomendado
Clasificación