AT32F403A串口USART1配置

本文详细介绍了USART(通用同步异步收发器)的功能特点及其在嵌入式系统中的应用,包括可配置的通信模式、波特率发生器、帧格式等。此外,还提供了通过USART实现串口printf打印的方法,包括必要的头文件定义、串口初始化配置以及主程序的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、USART介绍

通用同步异步收发器(USART)是一个能通过多种不同的配置与使用不同的数据格式的外设进行通信的
通用接口,同时支持异步全双工,异步半双工以及同步传输。USART 提供了可编程的波特率发生器,根
据系统频率以及分频系数的不同,可产生高达 7.5MBits/s 的波特率,用户可以通过配置系统时钟以及分
频系数以此产生所需要的特定通信频率。
USART 除了支持标准的 NRZ 异步以及同步收发通信协议外,还支持一些常用的其他类型的串行通信协
议,如 LIN(局域互联网),IrDA(红外数据组织)SIRENDEC 规范,ISO7816-3 标准的异步智能卡协议,
以及 CTS/RTS(Clear To Send/Request To Send)硬件流操作。
USART 还支持多处理器通信,以及可配置通过空闲帧或 ID 匹配唤醒的静默模式,以此搭建 USART 网
络,并且同时支持使用 DMA 进行数据的收发,以此实现高速通信。
图 12-1 USART框图
在这里插入图片描述
USART 主要特性如下所列 :
 可编程配置的全双工或半双工通信
― 全双工异步通信
― 单线半双工通信
 可编程配置的通信模式
― NRZ标准格式(Mark/Space)
― LIN(局域互联网):LIN主机有发送间隔帧的能力以及LIN从机有检测间隔帧的能力
― IrDA SIR(串行红外): 在普通模式下持续时间为3/16位,在红外低功耗模式下位
持续时间可调
― ISO7816-3标准里定义的异步智能卡协议: 智能卡模式支持0.5或1.5个停止位
― RS-232 CTS/RTS(Clear To Send/Request To Send)硬件流操作
― 通过静默模式实现多处理器通信(具有ID匹配和总线空闲两种可编程配置的唤醒方式)
― 同步模式
 可编程配置的波特率发生器
― 发送和接收共用的可编程波特率,最高达7.5MBits/s
 可编程配置的帧格式
― 可编程的数据位位数(8位或9位)
― 可编程的停止位位数-支持1或2个停止位
― 可编程的校验控制:发送方具备发送校验位的能力,接收方具备对接收到的数据进行
校验的能力
 可编程配置的 DMA 多缓冲器通信
 可编程配置的独立的发送器和接收器使能位
 可编程配置的输出 CLK 的相位和极性以及频率
 检测标志
― 接收缓冲器满
― 发送缓冲器空
― 传输完成标志
 四个错误检测标志
― 溢出错误
― 噪声错误
― 帧错误
― 校验错误
 可编程配置的 10 个带标志的中断源
― CTSF改变
― LIN间隔帧检测
― 发送数据寄存器空
― 发送完成
― 接收数据寄存器满
― 检测到总线为空闲
― 溢出错误
― 帧错误
― 噪声错误
― 校验错误

二、串口printf打印

在嵌入式系统中,通过串口打印log是非常重要的调试手段,但是直接调用底层驱动打印信息非常不方便,在c语言中一般使用printf打印基本的显示信息,而默认printf的结果不会通过串口发送,所以需要对printf的输出进行重定向。

1.头文件定义

/**************** define print uart ******************/
#define PRINT_UART                       USART1
#define PRINT_UART_CRM_CLK               CRM_USART1_PERIPH_CLOCK
#define PRINT_UART_TX_PIN                GPIO_PINS_9
#define PRINT_UART_TX_GPIO               GPIOA
#define PRINT_UART_TX_GPIO_CRM_CLK       CRM_GPIOA_PERIPH_CLOCK

2.串口初始化配置

/**
  * @brief  initialize uart
  * @param  baudrate: uart baudrate
  * @retval none
  */
void uart_print_init(uint32_t baudrate)
{
  gpio_init_type gpio_init_struct;

  /* enable the uart and gpio clock */
  crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);
  crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);

  gpio_default_para_init(&gpio_init_struct);

  /* configure the uart tx pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(PRINT_UART_TX_GPIO, &gpio_init_struct);

  /* configure uart param */
  usart_init(PRINT_UART, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(PRINT_UART, TRUE);
  usart_enable(PRINT_UART, TRUE);
}


3.串口printf输出定义

宏定义并实现具体的发送函数

   代码在编译时首先判断__GNUC__有无定义,之后将PUTCHAR_PROTOTYPE替换成具体的定义。在keil5中,使用fputc函数,所以其实最后是重写了fputc的实现,在该函数中,调用串口的发送函数,每次发送一个字符。
#if defined (__GNUC__) && !defined (__clang__)
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

/**
  * @brief  retargets the c library printf function to the usart.
  * @param  none
  * @retval none
  */
PUTCHAR_PROTOTYPE
{
  while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET);
  usart_data_transmit(PRINT_UART, ch);
  return ch;
}

4. 主程序串口初始化配置

/**
  **************************************************************************
  * @file     main.c
  * @version  v2.0.9
  * @date     2022-04-25
  * @brief    main program
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "at32f403a_407_board.h"
#include "at32f403a_407_clock.h"

/** @addtogroup AT32F403A_periph_examples
  * @{
  */

/** @addtogroup 403A_USART_printf USART_printf
  * @{
  */

__IO uint32_t time_cnt = 0;

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
  system_clock_config();
  at32_board_init();
  uart_print_init(115200);

  /* output a message on hyperterminal using printf function */
  printf("usart printf example: retarget the c library printf function to the usart\r\n");

  while(1)
  {
    printf("usart printf counter: %u\r\n",time_cnt++);
    delay_sec(1);
  }
}

/**
  * @}
  */

/**
  * @}
  */

### AT32F403A UART DMA Receive and TIM7 Periodic Transmit Example Code For implementing the functionality of receiving data via UART using Direct Memory Access (DMA) on an AT32F403A microcontroller, while periodically transmitting data with Timer 7, one can follow a structured approach to configure these peripherals accordingly[^1]. Below is an illustrative example demonstrating how this setup might be achieved. #### Configuration Overview The configuration involves initializing UART for communication purposes, setting up DMA channels specifically dedicated to handling reception tasks efficiently without CPU intervention during transfers, configuring Timer 7 as a periodic timer that triggers transmission events at set intervals, and ensuring proper interrupt management so operations occur seamlessly between components involved in both processes. #### Initialization Functions Initialization functions are crucial for establishing correct settings before any operation begins. These include enabling clocks related to used peripherals like USARTx/DMAy/TIMz where 'x', 'y' & 'z' represent specific instances being utilized within hardware design; defining pin modes associated with serial interface lines such as TX/RX pins connected externally through GPIOs configured appropriately either directly or indirectly depending upon application requirements; finally adjusting parameters inside each peripheral's registers according to desired functionalities required by software logic implemented later stages after initialization phase completes successfully. ```c #include "at32f4xx.h" // Define buffer size and buffers for received/transmitted data. #define BUFFER_SIZE 64 uint8_t rx_buffer[BUFFER_SIZE]; volatile uint8_t tx_buffer[BUFFER_SIZE]; void uart_dma_tim_init(void); void usart_send_array(uint8_t *data, uint16_t length); int main(void) { SystemCoreClockUpdate(); // Initialize UART, DMA, and TIM7 configurations. uart_dma_tim_init(); while(1){ // Main loop does not need to handle UART RX/TX here, // because it will be handled by DMA and TIM7 interrupts respectively. } } void uart_dma_tim_init() { /* Enable necessary clock */ rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART1); rcu_periph_clock_enable(RCU_DMA1); rcu_periph_clock_enable(RCU_TIM7); /* Configure PA9/PA10(TX/RX) as alternate function push-pull */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9 | GPIO_PIN_10); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9 | GPIO_PIN_10); gpio_af_select(GPIOA, GPIO_AF7, GPIO_PIN_9 | GPIO_PIN_10); /* USART1 configuration */ usart_deinit(USART1); usart_baudrate_set(USART1, 115200U); usart_word_length_set(USART1, USART_WL_8BIT); usart_stop_bit_set(USART1, USART_STB_1BIT); usart_parity_config(USART1, USART_PM_NONE); usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE); usart_receive_config(USART1, USART_RECEIVE_ENABLE); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); usart_enable(USART1); /* DMA channel configuration for USART1_RX */ dma_parameter_struct dma_initstructure; dma_deinit(DMA1_Channel5); dma_initstructure.direction = DMA_PERIPHERAL_TO_MEMORY; dma_initstructure.memory_addr = (uint32_t)&rx_buffer[0]; dma_initstructure.periph_addr = (uint32_t)&USART1->DR; dma_initstructure.priority = DMA_PRIORITY_HIGH; dma_initstructure.number = BUFFER_SIZE; dma_initstructure.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_initstructure.periph_width = DMA_PERIPH_WIDTH_8BIT; dma_initstructure.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_initstructure.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init(DMA1_Channel5,&dma_initstructure); nvic_irq_enable(DMA1_Channel5_IRQn, 0, 0); dma_circular_mode_enable(DMA1_Channel5); dma_channel_enable(DMA1_Channel5); /* TIM7 configuration for periodical event generation */ timer_deinit(TIM7); timer_prescaler_config(TIM7, 83, TIMER_COUNTER_EDGE_DOWN); timer_autoreload_write(TIM7, 9999); timer_interrupt_enable(TIM7, TIMER_INT_UP); nvic_irq_enable(TIM7_IRQn, 0, 0); timer_enable(TIM7); /* Clear pending flags just in case */ tim_clear_flag(TIM7,TIMER_FLAG_UPDATE); } ``` In addition to the above initializations, appropriate Interrupt Service Routines must also be defined to manage incoming/outgoing transmissions effectively when triggered by corresponding hardware signals indicating completion states reached during ongoing activities involving either direct memory access mechanisms employed under reception scenarios managed automatically behind scenes thanks largely due efficient implementation provided out-of-box support offered natively across many modern embedded platforms including but limited only those based around ARM Cortex-M series processors which power Atmel SAM family members among others supporting similar feature sets today. Interrupt service routines should process completed receptions from DMA and prepare new data for sending once Timer 7 indicates readiness: ```c extern volatile uint8_t tx_buffer[]; void DMA1_Channel5_IRQHandler(void) { if(dma_flag_get(DMA1_Channnel5,DMA_INT_FTFIF)==SET) { // Handle full transfer complete flag // This means we have received all expected bytes into our buffer now // Reset DMA stream ready for next round dma_stream_reset(DMA1_Channel5); // Prepare some
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

章鱼哥嵌入式开发

坚持不易,你们的鼓励是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值