5.28 USART 使用说明
本章说明 N32H49x 标准外设库中 USART 驱动的文件组成、46 个公开函数,以及 485、LIN、IrDA 等 16 个示例。寄存器位定义、分数波特率计算、FIFO 与阈值、多处理器通信、同步模式、单线半双工、智能卡、IrDA、硬件流控与接收器超时等机制请配合用户手册的 USART 章节阅读。
5.28.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32h49x_std_periph_driver/inc/n32h49x_usart.h |
定义 USART_InitType、USART_ClockInitType 结构体,以及字长、停止位、校验、模式、硬件流控、过采样、时钟、中断、DMA、唤醒、LIN、IrDA、智能卡、半双工、标志与 FIFO 深度等宏,并声明 46 个公开函数 |
firmware/n32h49x_std_periph_driver/src/n32h49x_usart.c |
实现上述 46 个函数:复位与初始化、数据收发、标志与中断状态查询、DMA、多处理器、LIN、同步、半双工、智能卡、IrDA、驱动器使能与 FIFO 配置 |
projects/n32h49x_EVAL/examples/USART/ |
USART 示例根目录,含 16 个示例:485_Master、485_Slave、DMA_Interrupt、DMA_Polling、FIFO_Interrupt、HalfDuplex、HardwareFlowCtrl、Interrupt、Transmit_Receive、LIN_Master、LIN_Slave、MultiProcessor、Polling、Printf、SmartCard、Synchronous |
projects/n32h49x_EVAL/examples/USART/Polling/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32h49x_EVAL/bsp/ |
本模块部分 Demo 引用的板级支持文件:评估板定义、毫秒与微秒延时、串口打印重定向 |
5.28.2 API 参考
以下 46 个公开函数按 n32h49x_usart.h 的声明顺序分为 8 组;每个条目给出功能摘要与 n32h49x_usart.c 中该函数正上方的注释原文。
复位与初始化
USART_DeInit、USART_Init、USART_StructInit、USART_ClockInit、USART_ClockStructInit、USART_Enable
中断、DMA 与多机通信
USART_ConfigInt、USART_EnableDMA、USART_SetAddr、USART_ConfigWakeUpMode、USART_EnableRcvWakeUp
LIN 与数据收发
USART_ConfigLINBreakDetectLength、USART_EnableLIN、USART_SendData、USART_ReceiveData、USART_SendBreak
智能卡、IrDA 与半双工
USART_SetGuardTime、USART_SetPrescaler、USART_EnableSmartCard、USART_SetSmartCardNACK、USART_EnableHalfDuplex、USART_ConfigIrDAMode、USART_EnableIrDA
标志与中断状态
USART_GetFlagStatus、USART_ClrFlag、USART_ClrRTOFlag、USART_GetIntStatus
驱动器使能、引脚交换与空闲帧控制
USART_IdleFrameSet、USART_PinSwapSet、USART_CfgDriverAssertTime、USART_CfgDriverdeassertTime、USART_DriverPolaritySet、USART_DriverModeSet
错误丢弃与接收超时
USART_FEFDiscardSet、USART_NEFDiscardSet、USART_PEFDiscardSet、USART_RTOSet
FIFO 与超时宽度
USART_GetTxFIFO_Num、USART_GetRxFIFO_Num、USART_CfgRxFIFOThreshold、USART_CfgTxFIFOThreshold、USART_ClrFIFO、USART_FIFOModeSet、USART_IdleFrameWidthSet、USART_CfgRTOWidth、USART_FirstByteDelayFixSet
void USART_DeInit(USART_Module* USARTx)将 USARTx 外设寄存器还原为默认复位值。
name USART_DeInit
fun Deinitializes the USARTx peripheral registers to their default reset values.
param U(S)ARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return none
void USART_Init(USART_Module* USARTx, USART_InitType* USART_InitStruct)根据 USART_InitStruct 初始化 USARTx 外设。
name USART_Init
fun Initializes the USARTx peripheral according to USART_InitStruct.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_InitStruct (The input parameters must be the following values):
- buad_rate :
- (((buad_rate) > 0) && ((buad_rate) < 0x00E4E1C0))
- WordLength
- USART_WL_8B
- USART_WL_9B
- StopBits
- USART_STPB_1
- USART_STPB_0_5
- USART_STPB_2
- USART_STPB_1_5
- Parity
- USART_PE_NO
- USART_PE_EVEN
- USART_PE_ODD
- Mode
- USART_MODE_RX
- USART_MODE_TX
- HardwareFlowControl
- USART_HFCTRL_NONE
- USART_HFCTRL_RTS
- USART_HFCTRL_CTS
- USART_HFCTRL_RTS_CTS
- OverSampling
- USART_8OVER
- USART_16OVER
return none
void USART_StructInit(USART_InitType* USART_InitStruct)用默认值填充 USART_InitStruct 的每个成员。
name USART_StructInit.
fun Fills each USART_InitStruct member with its default value.
param USART_InitStruct (The input parameters must be the following values):
- BaudRate
- WordLength
- StopBits
- Parity
- Mode
- OverSampling
return none
void USART_ClockInit(USART_Module* USARTx, USART_ClockInitType* USART_ClockInitStruct)根据 USART_ClockInitStruct 中的参数初始化 USARTx 的时钟。
name USART_ClockInit
fun Initializes the USARTx peripheral Clock according to the specified parameters in the USART_ClockInitStruct.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
param USART_ClockInitStruct (The input parameters must be the following values):
- Clock :
- USART_CLK_DISABLE
- USART_CLK_ENABLE
- USART_Clock_Polarity
- USART_CLKPOL_LOW
- USART_CLKPOL_HIGH
- USART_Clock_Phase
- USART_CLKPHA_1EDGE
- USART_CLKPHA_2EDGE
- USART_Last_Bit
- USART_CLKLB_DISABLE
- USART_CLKLB_ENABLE
return none
note The Smart Card and Synchronous modes are not available for UART5/UART6/UART7/UART8.
void USART_ClockStructInit(USART_ClockInitType* USART_ClockInitStruct)用默认值填充 USART_ClockInitStruct 的每个成员。
name USART_ClockStructInit
fun Fills each USART_ClockInitStruct member with its default value.
param USART_ClockInitStruct (The input parameters must be the following values):
- Clock
- USART_Clock_Polarity
- USART_Clock_Phase
- USART_Last_Bit
return none
void USART_Enable(USART_Module* USARTx, FunctionalState Cmd)使能或禁用指定的 USART 外设。
name USART_Enable
fun Enables or disables the specified USART peripheral.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_ConfigInt(USART_Module* USARTx, uint32_t USART_INT, FunctionalState Cmd)使能或禁用指定的 USART 中断。
name USART_ConfigInt
fun Enables or disables the specified USART interrupts.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_INT (The input parameters must be the following values):
- USART_INT_PEF Parity Error interrupt
- USART_INT_TXC Transmission complete interrupt
- USART_INT_TXDE Transmit Data Register empty interrupt
- USART_INT_RXDNE Receive Data register not empty interrupt
- USART_INT_IDLEF Idle line detection interrupt
- USART_INT_RTOE Receiver timeout interrupt
- USART_INT_LINBD LIN Break detection interrupt
- USART_INT_ERRF Error interrupt(Frame error, noise error, overrun error)
- USART_INT_CTSF CTS change interrupt
- USART_INT_TXFTE TXFIFO threshold interrupt enable
- USART_INT_RXFTE RXFIFO threshold interrupt enable
- USART_INT_RXFEE RXFIFO empty interrupt enable
- USART_INT_TXFEE TXFIFO empty interrupt enable
- USART_INT_RXFFE RXFIFO full interrupt enable
- USART_INT_TXFFE TXFIFO full interrupt enable
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_EnableDMA(USART_Module* USARTx, uint32_t USART_DMAReq, FunctionalState Cmd)使能或禁用 USART 的 DMA 接口。
name USART_EnableDMA
fun Enables or disables the USART's DMA interface.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_DMAReq (The input parameters must be the following values):
- USART_DMAREQ_TX USART DMA transmit request
- USART_DMAREQ_RX USART DMA receive request
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_SetAddr(USART_Module* USARTx, uint8_t USART_Addr)设置 USART 节点的地址。
name USART_SetAddr
fun Sets the address of the USART node.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_Addr (The input parameters must be the following values):
- (((USART_Addr)>=0x00)&&((USART_Addr)<0x10))
return none
void USART_ConfigWakeUpMode(USART_Module* USARTx, uint32_t USART_WakeUpMode)选择 USART 的唤醒方式。
name USART_ConfigWakeUpMode
fun Selects the USART WakeUp method.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_WakeUpMode (The input parameters must be the following values):
- USART_WUM_IDLELINE WakeUp by an idle line detection
- USART_WUM_ADDRMASK WakeUp by an address mark
return none
void USART_EnableRcvWakeUp(USART_Module* USARTx, FunctionalState Cmd)判断 USART 是否处于静默模式。
name USART_EnableRcvWakeUp
fun Determines if the USART is in mute mode or not.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_ConfigLINBreakDetectLength(USART_Module* USARTx, uint32_t USART_LINBreakDetectLength)设置 USART 的 LIN 断开检测长度。
name USART_ConfigLINBreakDetectLength
fun Sets the USART LIN Break detection length.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_LINBreakDetectLength (The input parameters must be the following values):
- USART_LINBDL_10B 10-bit break detection
- USART_LINBDL_11B 11-bit break detection
return none
void USART_EnableLIN(USART_Module* USARTx, FunctionalState Cmd)使能或禁用 USART 的 LIN 模式。
name USART_EnableLIN
fun Enables or disables the USART's LIN mode.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_SendData(USART_Module* USARTx, uint32_t Data)通过 USARTx 外设发送单个数据。
name USART_SendData
fun Transmits single data through the USARTx peripheral.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Data :
- the data to transmit
return none
uint32_t USART_ReceiveData(USART_Module* USARTx)返回 USARTx 外设最近一次接收到的数据。
name USART_ReceiveData
fun Returns the most recent received data by the USARTx peripheral.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return none
void USART_SendBreak(USART_Module* USARTx)发送断开字符。
name USART_SendBreak
fun Transmits break characters.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return none
void USART_SetGuardTime(USART_Module* USARTx, uint8_t USART_GuardTime)设置指定 USART 的保护时间。
name USART_SetGuardTime
fun Sets the specifies USART guard time.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
param USART_GuardTime:
- specifies the guard time
return none
void USART_SetPrescaler(USART_Module* USARTx, uint8_t USART_Prescaler)设置系统时钟预分频。
name USART_SetPrescaler
fun Sets the system clock prescaler.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_Prescaler:
- specifies the prescaler clock
return none
void USART_EnableSmartCard(USART_Module* USARTx, FunctionalState Cmd)使能或禁用 USART 的智能卡模式。
name USART_EnableSmartCard
fun Enables or disables the USART's Smart Card mode.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_SetSmartCardNACK(USART_Module* USARTx, FunctionalState Cmd)使能或禁用 NACK 发送。
name USART_SetSmartCardNACK
fun Enables or disables NACK transmission.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_EnableHalfDuplex(USART_Module* USARTx, FunctionalState Cmd)使能或禁用 USART 的单线半双工通信。
name USART_EnableHalfDuplex
fun Enables or disables the USART's Half Duplex communication.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void USART_ConfigIrDAMode(USART_Module* USARTx, uint32_t USART_IrDAMode)配置 USART 的 IrDA 接口。
name USART_ConfigIrDAMode
fun Configures the USART's IrDA interface.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_IrDAMode (The input parameters must be the following values):
- USART_IRDAMODE_LOWPPWER
- USART_IRDAMODE_NORMAL
return none
void USART_EnableIrDA(USART_Module* USARTx, FunctionalState Cmd)使能或禁用 USART 的 IrDA 接口。
name USART_EnableIrDA
fun Enables or disables the USART's IrDA interface.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
FlagStatus USART_GetFlagStatus(USART_Module* USARTx, uint32_t USART_FLAG)检查指定的 USART 标志是否置位。
name USART_GetFlagStatus
fun Checks whether the specified USART flag is set or not.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_FLAG (The input parameters must be the following values):
- USART_FLAG_FELOSE Received Data FE Error Discard Flag
- USART_FLAG_NELOSE Received Data NE Error Discard Flag
- USART_FLAG_PELOSE Received Data PE Error Discard Flag
- USART_FLAG_RTO recevier timeout Flag
- USART_FLAG_FEF Framing error Flag
- USART_FLAG_NEF Noise error flag Flag
- USART_FLAG_OREF Overrun error
- USART_FLAG_PEF Parity error
- USART_FLAG_LINBD LIN break detection flag
- USART_FLAG_CTSF CTS Change flag
- USART_FLAG_RXDNE Receive data register not empty flag
- USART_FLAG_TXC Transmission Complete flag
- USART_FLAG_TXDE Transmit data register empty flag
- USART_FLAG_IDLEF Idle Line detection flag
- USART_FLAG_TXFT TX FIFO threshold flag
- USART_FLAG_RXFT RX FIFO threshold flag
- USART_FLAG_RXFE RX FIFO empty flag
- USART_FLAG_TXFE TX FIFO empty flag
- USART_FLAG_RXFF RX FIFO full flag
- USART_FLAG_TXFF TX FIFO full flag
return USART_FLAG
- SET
- RESET
void USART_ClrFlag(USART_Module* USARTx, uint32_t USART_FLAG)清除 USARTx 的待处理标志。
name USART_ClrFlag
fun Clears the USARTx's pending flags.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_FLAG (The input parameters must be the following values):
- USART_FLAG_FELOSE Received Data FE Error Discard Flag
- USART_FLAG_NELOSE Received Data NE Error Discard Flag
- USART_FLAG_PELOSE Received Data PE Error Discard Flag
- USART_FLAG_LINBD LIN break detection flag
- USART_FLAG_CTSF CTS Change flag
- USART_FLAG_RXDNE Receive data register not empty flag
- USART_FLAG_TXC Transmission Complete flag
return none
note
- PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun
error) and IDLE (Idle line detected) flags are cleared by software
sequence: a read operation to USART_STS register (USART_GetFlagStatus())
followed by a read operation to USART_DAT register (USART_ReceiveData()).
- RXNE flag can be also cleared by a read to the USART_DAT register
(USART_ReceiveData()).
- TC flag can be also cleared by software sequence: a read operation to
USART_SR register (USART_GetFlagStatus()) followed by a write operation
to USART_DAT register (USART_SendData()).
- TXE flag is cleared only by a write to the USART_DAT register
(USART_SendData()).
- RTO flag is cleared only by a write 1 to the USART_CTRL2.RTOCF bit.
(USART_ClrRTOFlag()).
void USART_ClrRTOFlag(USART_Module* USARTx)清除 USARTx 的 RTO 待处理标志。
name USART_ClrRTOFlag
fun Clears the USARTx's RTO pending flag.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return none
INTStatus USART_GetIntStatus(USART_Module* USARTx, uint32_t USART_INT)检查指定的 USART 中断是否置位。
name USART_GetIntStatus
fun Checks whether the specified USART interrupt has set or not.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param USART_INT (The input parameters must be the following values):
- USART_INT_PEF Parity Error interrupt
- USART_INT_TXC Transmission complete interrupt
- USART_INT_TXDE Transmit Data Register empty interrupt
- USART_INT_RXDNE Receive Data register not empty interrupt
- USART_INT_IDLEF Idle line detection interrupt
- USART_INT_RTOE Receiver timeout interrupt
- USART_INT_LINBD LIN Break detection interrupt
- USART_INT_ERRF Error interrupt(Frame error, noise error, overrun error)
- USART_INT_CTSF CTS change interrupt
- USART_INT_TXFTE TXFIFO threshold interrupt enable
- USART_INT_RXFTE RXFIFO threshold interrupt enable
- USART_INT_RXFEE RXFIFO empty interrupt enable
- USART_INT_TXFEE TXFIFO empty interrupt enable
- USART_INT_RXFFE RXFIFO full interrupt enable
- USART_INT_TXFFE TXFIFO full interrupt enable
return bitstatus
- SET
- RESET
void USART_IdleFrameSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用空闲帧可控功能。
name USART_IdleFrameSet
fun Idle frame controllable enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_PinSwapSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用 TX/RX 引脚交换。
name USART_PinSwapSet
fun Swap TX/RX pins enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART9
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
使用提示: 源码注释的实例列表把 USART9 写了两遍并漏掉 USART4,实际受支持的实例以头文件声明与用户手册为准。
void USART_CfgDriverAssertTime(USART_Module* USARTx,uint32_t Time)设置驱动器使能的有效时间。
name USART_CfgDriverAssertTime
fun Set Driver Enable assertion time.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Time:(The input parameters must be the following values)
- 0x01 ~ 0x1F
return none
void USART_CfgDriverdeassertTime(USART_Module* USARTx,uint32_t Time)设置驱动器使能的无效时间。
name USART_CfgDriverdeassertTime
fun Set Driver Enable deassertion time.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Time:(The input parameters must be the following values)
- 0x01 ~ 0x1F
return none
void USART_DriverPolaritySet(USART_Module* USARTx,FunctionalState Cmd)选择驱动器使能的极性。
name USART_DriverPolaritySet
fun Driver enable polarity selection.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_DriverModeSet(USART_Module* USARTx,FunctionalState Cmd)选择驱动器使能的模式。
name USART_DriverModeSet
fun Driver enable mode selection.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_FEFDiscardSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用 FEF 数据丢弃。
name USART_FEFDiscardSet
fun FEF Data Discard enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_NEFDiscardSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用 NEF 数据丢弃。
name USART_NEFDiscardSet
fun NEF Data Discard enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_PEFDiscardSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用 PEF 数据丢弃。
name USART_PEFDiscardSet
fun PEF Data Discard enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_RTOSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用接收超时。
name USART_RTOSet
fun Receiver timeout enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
uint32_t USART_GetTxFIFO_Num(USART_Module* USARTx)返回 TXFIFO 中的有效数据个数。
name USART_GetTxFIFO_Num
fun number of TXFIFO valid data.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return 0x00~0x08
uint32_t USART_GetRxFIFO_Num(USART_Module* USARTx)返回 RXFIFO 中的有效数据个数。
name USART_GetRxFIFO_Num
fun number of RXFIFO valid data.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return 0x00~0x08
void USART_CfgRxFIFOThreshold(USART_Module* USARTx,uint32_t threshold)配置 RXFIFO 阈值。
name USART_CfgRxFIFOThreshold
fun RXFIFO threshold configuration.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param threshold (The input parameters must be the following values):
- USART_FIFO_DEEP1
- USART_FIFO_DEEP2
- USART_FIFO_DEEP4
- USART_FIFO_DEEP6
- USART_FIFO_DEEP7
- USART_FIFO_DEEP8
return none
void USART_CfgTxFIFOThreshold(USART_Module* USARTx,uint32_t threshold)配置 TXFIFO 阈值。
name USART_CfgTxFIFOThreshold
fun TXFIFO threshold configuration.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param threshold (The input parameters must be the following values):
- USART_FIFO_DEEP1
- USART_FIFO_DEEP2
- USART_FIFO_DEEP4
- USART_FIFO_DEEP6
- USART_FIFO_DEEP7
- USART_FIFO_DEEP8
return none
void USART_ClrFIFO(USART_Module* USARTx)清除 FIFO。
name USART_ClrFIFO
fun FIFO clear.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
return none
void USART_FIFOModeSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用 FIFO 模式。
name USART_FIFOModeSet
fun FIFO mode enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
void USART_IdleFrameWidthSet(USART_Module* USARTx,uint32_t Width)配置空闲帧宽度。
name USART_CfgIdleFrameWidth
fun configure Idle frame width.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Width:(The input parameters must be the following values)
- 0x0000 ~ 0xFFFF
return none
使用提示: 源码注释中的函数名为 USART_CfgIdleFrameWidth,与头文件声明的 USART_IdleFrameWidthSet 不一致,属驱动注释笔误,实际功能以函数名为准。
void USART_CfgRTOWidth(USART_Module* USARTx,uint32_t Width)配置接收超时宽度。
name USART_CfgRTOWidth
fun configure receive timeout width.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Width:(The input parameters must be the following values)
- 0x00000000 ~ 0x0FFFFFFF
return none
void USART_FirstByteDelayFixSet(USART_Module* USARTx,FunctionalState Cmd)使能或禁用首字节延时固定。
name USART_FirstByteDelayFixSet
fun First byte delay fixed enable or disable.
param USARTx (The input parameters must be the following values):
- USART1
- USART2
- USART3
- USART4
- USART9
- UART5
- UART6
- UART7
- UART8
- UART10
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none
5.28.3 Demo 示例说明
本节说明 USART 的 16 个示例:Polling、Interrupt、DMA_Polling、DMA_Interrupt 分别用查询、中断与 DMA 完成双机收发,HardwareFlowCtrl 与 HalfDuplex 演示硬件流控和单线半双工,485_Master、485_Slave 演示 RS-485 收发,LIN_Master、LIN_Slave 演示 LIN 帧收发,Synchronous 演示同步模式与 SPI 通信,SmartCard 演示智能卡协议与 ATR 解析,Transmit_Receive 演示 IrDA 红外收发,MultiProcessor 演示多处理器地址唤醒,FIFO_Interrupt 演示 FIFO 阈值中断接收,Printf 把 printf 重定向到串口。
5.28.3.1 485/485_Master RS-485 主机收发
工程目录: projects/n32h49x_EVAL/examples/USART/485/485_Master/
初始化串口、485 收发器引脚与中断→把固定文本经 485 总线发往从机→等待从机回传等长数据→比较发送与接收缓冲区→串口打印测试结果
| 项目 | 源码解读 |
|---|---|
| 功能 | 两块评估板通过 RS-485 总线做半双工收发,主机经 USARTz(UART5)把固定文本发给从机,再接收从机回传的同一文本并比对。 |
| 源码组成 | src/main.c:日志初始化、时钟与 GPIO 配置、USART 参数配置、485 驱动器使能控制与数据比对;inc/main.h:USARTz 实例、引脚、复用号与中断宏;src/n32h49x_it.c:USARTz_IRQHandler 收发中断与错误标志清除;readme.txt:功能、环境、引脚连接与测试步骤。引脚宏来自 bsp/,log_info 来自 bsp/src/log.c。 |
| 关键配置 | USARTz 为 UART5,Rx 为 PA5(GPIO_AF21)、Tx 为 PA4(GPIO_AF20)、DE 为 PA3(GPIO_AF19),均配置为复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验、无硬件流控,收发均使能。 DE 有效时间 1、无效时间 0,极性 DISABLE、驱动使能模式 ENABLE;NVIC 分组 2、UART5 子优先级 1。 |
| 程序与数据路径 | main 先调用 log_init,配置时钟、NVIC 与 GPIO,把 USARTz 初始化为 115200、8 位、1 位停止位、无校验并配置 485 驱动器,使能收发中断与 USART。随后忙等 RxCounter2 达到接收长度,调用 Buffercmp 比较发送与接收缓冲区,并按结果打印 OK 或 Fail。 |
| 主要 API | USART_StructInit、USART_Init、USART_CfgDriverAssertTime、USART_CfgDriverdeassertTime、USART_DriverPolaritySet、USART_DriverModeSet、USART_ConfigInt、USART_Enable、USART_ReceiveData、USART_SendData |
| 验证方法 | 先给从机上电,再给主机上电,复位运行; 主机串口打印 N32H49x 485 Master test START,从机回传完成后打印 N32H49x 485 Master test OK 表示数据一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;Slave 先上电、Master 后上电; J33、J34、J35 跳线帽需连接。 工程基于 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用 USARTz(UART5)配合 485 收发器,在两块评估板之间完成一次带驱动器使能控制的中断收发。
数据路径: USARTz 发送 TxBuffer2 → 485 收发器 → 从机 USARTz 接收 → USARTz_IRQHandler 逐字节写入 RxBuffer2 → 从机回传 → 主机 Buffercmp 比较收发缓冲区 → log_info 打印结果
1. 用宏定义 485 所用的实例、引脚与复用号。 inc/main.h 把 USARTz 指向 UART5,并给出 Rx、Tx、DE 三个引脚与对应复用号,后续配置都通过这组宏访问。
#define USARTz UART5
#define USARTz_CLK RCC_APB1_PERIPHEN_UART5
#define USARTz_GPIO GPIOA
#define USARTz_GPIO_CLK RCC_AHB_PERIPHEN_GPIOA
#define USARTz_RxPin GPIO_PIN_5
#define USARTz_TxPin GPIO_PIN_4
#define USARTz_DEPin GPIO_PIN_3
#define USARTz_Rx_GPIO_AF GPIO_AF21
#define USARTz_Tx_GPIO_AF GPIO_AF20
#define USARTz_DE_GPIO_AF GPIO_AF19
更换实例或引脚时,只需改动这一组宏。
2. 配置 485 收发器的驱动器使能。 使能 DE 模式后,USART 会在发送时自动拉高 DE 引脚;有效时间设为 1、无效时间设为 0,极性为低有效。
USART_CfgDriverAssertTime(USARTz,1);
USART_CfgDriverdeassertTime(USARTz,0);
USART_DriverPolaritySet(USARTz,DISABLE);
USART_DriverModeSet(USARTz,ENABLE);
DEAT 在 DEM 使能后不能为 0,因此这里取最小值 1。
3. 使能收发中断并启动 USART。 主机同时打开发送与接收中断,USART_Enable 置位 UEN 后开始收发。
USART_ConfigInt(USARTz, USART_INT_TXDE,ENABLE);
USART_ConfigInt(USARTz, USART_INT_RXDNE,ENABLE);
/* Enable the USARTz */
USART_Enable(USARTz, ENABLE);
4. 在中断里搬移收发数据。 接收中断把数据写入 RxBuffer2,收满后关中断;发送中断按 TxBuffer2 逐字节写出。
void USARTz_IRQHandler(void)
{
if ((USART_GetFlagStatus(USARTz, USART_FLAG_RXDNE) != RESET) && (USART_GetIntStatus(USARTz, USART_INT_RXDNE) != RESET))
{
/* Read one byte from the receive data register */
RxBuffer2[RxCounter2++] = USART_ReceiveData(USARTz);
if (RxCounter2 == NbrOfDataToRead1)
{
/* Disable the USARTz Receive interrupt */
USART_ConfigInt(USARTz, USART_INT_RXDNE,DISABLE);
}
}
对应源码: src/main.c、inc/main.h、src/n32h49x_it.c
5.28.3.2 485/485_Slave RS-485 从机收发
工程目录: projects/n32h49x_EVAL/examples/USART/485/485_Slave/
初始化串口、485 收发器与中断→仅使能接收中断接收主机数据→收满后比较接收数据与本地模板→使能发送中断把同一文本回传主机→串口打印比较结果
| 项目 | 源码解读 |
|---|---|
| 功能 | 两块评估板通过 RS-485 总线做半双工收发,从机经 USARTz(UART5)接收主机发来的固定文本并比对,随后把同一文本回传给主机。 |
| 源码组成 | src/main.c:日志初始化、时钟与 GPIO 配置、USART 参数配置、485 驱动器使能控制与先后启动收发中断;inc/main.h:USARTz 实例、引脚、复用号与中断宏;src/n32h49x_it.c:USARTz_IRQHandler 收发中断与错误标志清除;readme.txt:功能、环境、引脚连接与测试步骤。引脚宏来自 bsp/,log_info 来自 bsp/src/log.c。 |
| 关键配置 | USARTz 为 UART5,Rx 为 PA5(GPIO_AF21)、Tx 为 PA4(GPIO_AF20)、DE 为 PA3(GPIO_AF19),均配置为复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验、无硬件流控,收发均使能。 DE 有效时间 1、无效时间 0,极性 DISABLE、驱动使能模式 ENABLE;NVIC 分组 2、UART5 子优先级 1。 |
| 程序与数据路径 | main 先调用 log_init,配置时钟、NVIC 与 GPIO,把 USARTz 初始化为 115200、8 位、1 位停止位、无校验并配置 485 驱动器,只使能接收中断后启动 USART。收满 RxBuffer2 后调用 Buffercmp 比较收发缓冲区并打印 OK 或 Fail,再使能发送中断把同一文本回传给主机。 |
| 主要 API | USART_StructInit、USART_Init、USART_CfgDriverAssertTime、USART_CfgDriverdeassertTime、USART_DriverPolaritySet、USART_DriverModeSet、USART_ConfigInt、USART_Enable、USART_ReceiveData、USART_SendData |
| 验证方法 | 先给从机上电,再给主机上电,复位运行; 从机串口打印 N32H487ZEL7_EVB 485 Slave test START,与主机比对一致后打印 N32H487ZEL7_EVB 485 Slave test OK。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;Slave 先上电、Master 后上电; J33、J34、J35 跳线帽需连接。 工程基于 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例让从机先只开接收中断接收主机数据,比对一致后再打开发送中断把数据回传。
数据路径: 主机 USARTz 发送 → 485 总线 → 从机 USARTz 接收 → USARTz_IRQHandler 写入 RxBuffer2 → Buffercmp 比较 → 使能发送中断 → USARTz_IRQHandler 回传 TxBuffer2 → log_info 打印结果
1. 用宏定义 485 所用的实例、引脚与复用号。 inc/main.h 把 USARTz 指向 UART5,并给出 Rx、Tx、DE 三个引脚与对应复用号。
#define USARTz UART5
#define USARTz_CLK RCC_APB1_PERIPHEN_UART5
#define USARTz_GPIO GPIOA
#define USARTz_GPIO_CLK RCC_AHB_PERIPHEN_GPIOA
#define USARTz_RxPin GPIO_PIN_5
#define USARTz_TxPin GPIO_PIN_4
#define USARTz_DEPin GPIO_PIN_3
#define USARTz_Rx_GPIO_AF GPIO_AF21
#define USARTz_Tx_GPIO_AF GPIO_AF20
#define USARTz_DE_GPIO_AF GPIO_AF19
2. 先只使能接收中断并启动 USART。 从机先进入接收状态,等主机把数据发来。
/* Enable USARTz Receive and Transmit interrupts */
USART_ConfigInt(USARTz, USART_INT_RXDNE,ENABLE);
/* Enable the USARTz */
USART_Enable(USARTz, ENABLE);
3. 比对后打开发送中断回传数据。 收满后先比对收发缓冲区并打印结果,再使能发送中断,把同一文本发回给主机。
TransferStatus2 = Buffercmp(TxBuffer2, RxBuffer2, TxBufferSize2);
/* TransferStatus = PASSED, if the data transmitted and received are the same */
/* TransferStatus = FAILED, if the data transmitted and received are different */
if(TransferStatus2 == PASSED)
{
log_info(" N32H487ZEL7_EVB 485 Slave test OK \r\n");
}
else
{
log_info(" N32H487ZEL7_EVB 485 Slave test Fail \r\n");
}
/* Enable USARTz Receive and Transmit interrupts */
USART_ConfigInt(USARTz, USART_INT_TXDE,ENABLE);
4. 在中断里搬移收发数据。 接收中断把数据写入 RxBuffer2,收满后关中断;发送中断按 TxBuffer2 逐字节写出。
void USARTz_IRQHandler(void)
{
if ((USART_GetFlagStatus(USARTz, USART_FLAG_RXDNE) != RESET) && (USART_GetIntStatus(USARTz, USART_INT_RXDNE) != RESET))
{
/* Read one byte from the receive data register */
RxBuffer2[RxCounter2++] = USART_ReceiveData(USARTz);
if (RxCounter2 == NbrOfDataToRead1)
{
/* Disable the USARTz Receive interrupt */
USART_ConfigInt(USARTz, USART_INT_RXDNE,DISABLE);
}
}
对应源码: src/main.c、inc/main.h、src/n32h49x_it.c
5.28.3.3 DMA_Interrupt DMA 中断收发
工程目录: projects/n32h49x_EVAL/examples/USART/DMA_Interrupt/
初始化两路串口、DMA 与中断→DMA 把发送缓冲区搬移到两路发送寄存器→查询接收一路数据、中断接收另一路数据→等待两路 DMA 传输完成→比较两组收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)与 USARTz(UART5)互联,用 DMA 完成两路发送、分别用查询与中断完成接收,最后比对两组收发数据。 |
| 源码组成 | src/main.c:时钟、GPIO、NVIC、DMA 与 USART 配置、两路收发与数据比对;inc/main.h:两路实例、引脚、复用号、DMA 通道、标志与重映射宏;src/n32h49x_it.c:UART5_IRQHandler 接收中断与错误标志清除;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17、Rx PA15/GPIO_AF18),USARTz 为 UART5(Tx PA2/GPIO_AF20、Rx PA3/GPIO_AF21),均复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验; USARTy 的 Tx 用 DMA1_CH1(DMA_FLAG_TC1)、USARTz 的 Tx 用 DMA1_CH3(DMA_FLAG_TC3),方向均为存储器到外设。NVIC 分组 2、UART5 抢占与子优先级均为 0,只使能 USARTz 接收中断。 |
| 程序与数据路径 | main 依次配置时钟、NVIC、GPIO、DMA 与两路 USART,使能两路 DMA 收发请求与 USARTz 接收中断,再打开两路发送 DMA 通道与 USART。随后查询收到 TxBuffer2 的长度写入 RxBuffer1,等待两路 DMA 传输完成,最后用 Buffercmp 比较两组收发缓冲区。 |
| 主要 API | USART_Init、USART_EnableDMA、USART_ConfigInt、USART_Enable、USART_ReceiveData、USART_GetFlagStatus、DMA_Init、DMA_RequestRemap、DMA_EnableChannel、DMA_GetFlagStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Rx(PA3)、USART3_Rx(PA15)接 UART5_Tx(PA2),复位运行; 依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示两组数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;发送由 DMA 完成,接收一路为中断、一路为查询。 工程基于 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用 DMA 完成两路发送,并用查询与中断两种方式完成接收,最后比对两组数据。
数据路径: TxBuffer1 与 TxBuffer2 → DMA 搬移到两路发送数据寄存器 → 对端接收(USARTy 查询写入 RxBuffer1、USARTz 中断写入 RxBuffer2)→ Buffercmp 比较 → TransferStatus1 与 TransferStatus2
1. 用宏定义两路实例、引脚与 DMA 通道。 inc/main.h 用 _USART3_UART5_ 选择 USART3 与 UART5,并给出各自的引脚、复用号与发送 DMA 通道、标志、重映射。
#ifdef _USART3_UART5_
#define USARTy USART3
#define USARTy_CLK RCC_APB1_PERIPHEN_USART3
#define USARTy_GPIO GPIOA
#define USARTy_GPIO_CLK RCC_AHB_PERIPHEN_GPIOA
#define USARTy_RxPin GPIO_PIN_15
#define USARTy_TxPin GPIO_PIN_9
#define USARTy_Rx_GPIO_AF GPIO_AF18
#define USARTy_Tx_GPIO_AF GPIO_AF17
#define USARTy_DAT_Base (USART3_BASE + 0x10)
#define USARTy_Tx_DMA_Channel DMA1_CH1
#define USARTy_Tx_DMA_FLAG DMA_FLAG_TC1
#define USARTy_Tx_DMA_REMAP DMA_REMAP_USART3_TX
#define USARTz UART5
#define USARTz_CLK RCC_APB1_PERIPHEN_UART5
#define USARTz_GPIO GPIOA
#define USARTz_GPIO_CLK RCC_AHB_PERIPHEN_GPIOA
#define USARTz_RxPin GPIO_PIN_3
#define USARTz_TxPin GPIO_PIN_2
#define USARTz_Rx_GPIO_AF GPIO_AF21
#define USARTz_Tx_GPIO_AF GPIO_AF20
#define USARTz_DAT_Base (UART5_BASE + 0x10)
#define USARTz_Tx_DMA_Channel DMA1_CH3
#define USARTz_Tx_DMA_FLAG DMA_FLAG_TC3
#define USARTz_Tx_DMA_REMAP DMA_REMAP_UART5_TX
#define USARTz_IRQn UART5_IRQn
#endif
2. 配置两路发送 DMA 通道。 DMA_Configuration 把存储器端指向发送缓冲区、外设端指向数据寄存器,方向为存储器到外设,并打开对应的请求重映射。
/* USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config */
DMA_DeInit(USARTy_Tx_DMA_Channel);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = USARTy_DAT_Base;
DMA_InitStructure.MemAddr = (uint32_t)TxBuffer1;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
DMA_InitStructure.BufSize = TxBufferSize1;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
DMA_InitStructure.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(USARTy_Tx_DMA_Channel, &DMA_InitStructure);
DMA_RequestRemap(USARTy_Tx_DMA_REMAP,USARTy_Tx_DMA_Channel,ENABLE);
/* USARTz_Tx_DMA_Channel (triggered by USARTz Tx event) Config */
DMA_DeInit(USARTz_Tx_DMA_Channel);
DMA_InitStructure.PeriphAddr = USARTz_DAT_Base;
DMA_InitStructure.MemAddr = (uint32_t)TxBuffer2;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
DMA_InitStructure.BufSize = TxBufferSize2;
DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);
DMA_RequestRemap(USARTz_Tx_DMA_REMAP,USARTz_Tx_DMA_Channel,ENABLE);
3. 使能 DMA 请求并把发送交给 DMA。 先打开两路 DMA 收发请求与 USARTz 接收中断,再使能两路发送 DMA 通道并启动 USART。
/* Enable USARTy DMA Rx and TX request */
USART_EnableDMA(USARTy, USART_DMAREQ_RX | USART_DMAREQ_TX,ENABLE);
/* Enable USARTz DMA Rx and TX request */
USART_EnableDMA(USARTz, USART_DMAREQ_RX | USART_DMAREQ_TX,ENABLE);
/* Enable the USARTz Receive Interrupt */
USART_ConfigInt(USARTz, USART_INT_RXDNE,ENABLE);
/* Enable USARTy TX DMA Channel */
DMA_EnableChannel(USARTy_Tx_DMA_Channel,ENABLE);
/* Enable USARTz TX DMA Channel */
DMA_EnableChannel(USARTz_Tx_DMA_Channel,ENABLE);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
4. 在中断里接收另一路数据。 UART5_IRQHandler 在 USARTz 收到字节时写入 RxBuffer2,收满后关接收中断。
void UART5_IRQHandler(void)
{
if ((USART_GetFlagStatus(UART5, USART_FLAG_RXDNE) != RESET) && (USART_GetIntStatus(UART5, USART_INT_RXDNE) != RESET))
{
/* Read one byte from the receive data register */
RxBuffer2[RxCounter++] = USART_ReceiveData(UART5);
if (RxCounter == NbrOfDataToRead)
{
/* Disable the USART2 Receive interrupt */
USART_ConfigInt(UART5, USART_INT_RXDNE,DISABLE);
}
}
对应源码: src/main.c、inc/main.h、src/n32h49x_it.c
5.28.3.4 DMA_Polling DMA 查询收发
工程目录: projects/n32h49x_EVAL/examples/USART/DMA_Polling/
初始化两路串口与四路 DMA→DMA 完成两路发送与两路接收→逐一查询四路 DMA 的传输完成标志→比较两组收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)与 USARTz(UART5)互联,发送与接收全部由 DMA 在查询方式下完成,最后比对两组收发数据。 |
| 源码组成 | src/main.c:时钟、GPIO、DMA 与 USART 配置、四路 DMA 通道使能与数据比对;inc/main.h:两路实例、引脚、复用号、收发 DMA 通道、标志与重映射宏;src/n32h49x_it.c:中断服务函数(本示例未使用外设中断);readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17、Rx PA15/GPIO_AF18),USARTz 为 UART5(Tx PA2/GPIO_AF20、Rx PA3/GPIO_AF21),均复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验; USARTy 的 Tx/Rx 用 DMA1_CH4/CH5,USARTz 的 Tx/Rx 用 DMA1_CH7/CH6,发送方向为存储器到外设、接收方向为外设到存储器。 |
| 程序与数据路径 | main 依次配置时钟、GPIO、DMA 与两路 USART,使能两路 DMA 收发请求与四个 DMA 通道,再启动两路 USART。随后逐一查询四路 DMA 的传输完成标志,最后用 Buffercmp 比较两组收发缓冲区并写入 TransferStatus1 与 TransferStatus2。 |
| 主要 API | USART_Init、USART_EnableDMA、USART_Enable、DMA_Init、DMA_RequestRemap、DMA_EnableChannel、DMA_GetFlagStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Rx(PA3)、USART3_Rx(PA15)接 UART5_Tx(PA2),复位运行; 依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示两组数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;发送与接收都由 DMA 完成,全程只用查询、不产生外设中断。 工程基于 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例把两路收发全部交给 DMA,用查询方式逐一确认四路 DMA 传输完成,再比较两组数据。
数据路径: TxBuffer1 与 TxBuffer2 → 两路发送 DMA → 对端两路接收 DMA → RxBuffer1 与 RxBuffer2 → Buffercmp 比较 → TransferStatus1 与 TransferStatus2
1. 用宏定义两路实例、引脚与收发的 DMA 通道。 inc/main.h 用 _USART3_UART5_ 选择 USART3 与 UART5,并为每路给出发送、接收各一个 DMA 通道与完成标志。
#ifdef _USART3_UART5_
#define USARTy USART3
#define USARTy_CLK RCC_APB1_PERIPHEN_USART3
#define USARTy_GPIO GPIOA
#define USARTy_GPIO_CLK RCC_AHB_PERIPHEN_GPIOA
#define USARTy_RxPin GPIO_PIN_15
#define USARTy_TxPin GPIO_PIN_9
#define USARTy_Rx_GPIO_AF GPIO_AF18
#define USARTy_Tx_GPIO_AF GPIO_AF17
#define USARTy_DAT_Base (USART3_BASE + 0x10)
#define USARTy_Tx_DMA_Channel DMA1_CH4
#define USARTy_Tx_DMA_FLAG DMA_FLAG_TC4
#define USARTy_Rx_DMA_Channel DMA1_CH5
#define USARTy_Rx_DMA_FLAG DMA_FLAG_TC5
#define USARTy_Tx_DMA_REMAP DMA_REMAP_USART3_TX
#define USARTy_Rx_DMA_REMAP DMA_REMAP_USART3_RX
#define USARTz UART5
#define USARTz_CLK RCC_APB1_PERIPHEN_UART5
#define USARTz_GPIO GPIOA
#define USARTz_GPIO_CLK RCC_AHB_PERIPHEN_GPIOA
#define USARTz_RxPin GPIO_PIN_3
#define USARTz_TxPin GPIO_PIN_2
#define USARTz_Rx_GPIO_AF GPIO_AF21
#define USARTz_Tx_GPIO_AF GPIO_AF20
#define USARTz_DAT_Base (UART5_BASE + 0x10)
#define USARTz_Tx_DMA_Channel DMA1_CH7
#define USARTz_Tx_DMA_FLAG DMA_FLAG_TC7
#define USARTz_Rx_DMA_Channel DMA1_CH6
#define USARTz_Rx_DMA_FLAG DMA_FLAG_TC6
#define USARTz_Tx_DMA_REMAP DMA_REMAP_UART5_TX
#define USARTz_Rx_DMA_REMAP DMA_REMAP_UART5_RX
#endif
2. 配置四路 DMA 通道。 DMA_Configuration 中发送方向为存储器到外设、接收方向为外设到存储器,每路都打开对应的请求重映射。
/* USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config */
DMA_DeInit(USARTy_Tx_DMA_Channel);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = USARTy_DAT_Base;
DMA_InitStructure.MemAddr = (uint32_t)TxBuffer1;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
DMA_InitStructure.BufSize = TxBufferSize1;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
DMA_InitStructure.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(USARTy_Tx_DMA_Channel, &DMA_InitStructure);
DMA_RequestRemap(USARTy_Tx_DMA_REMAP,USARTy_Tx_DMA_Channel,ENABLE);
/* USARTy RX DMA1 Channel (triggered by USARTy Rx event) Config */
DMA_DeInit(USARTy_Rx_DMA_Channel);
DMA_InitStructure.PeriphAddr = USARTy_DAT_Base;
DMA_InitStructure.MemAddr = (uint32_t)RxBuffer1;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = TxBufferSize2;
DMA_Init(USARTy_Rx_DMA_Channel, &DMA_InitStructure);
DMA_RequestRemap(USARTy_Rx_DMA_REMAP,USARTy_Rx_DMA_Channel,ENABLE);
/* USARTz_Tx_DMA_Channel (triggered by USARTz Tx event) Config */
DMA_DeInit(USARTz_Tx_DMA_Channel);
DMA_InitStructure.PeriphAddr = USARTz_DAT_Base;
DMA_InitStructure.MemAddr = (uint32_t)TxBuffer2;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
DMA_InitStructure.BufSize = TxBufferSize2;
DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);
DMA_RequestRemap(USARTz_Tx_DMA_REMAP,USARTz_Tx_DMA_Channel,ENABLE);
/* USARTz RX DMA1 Channel (triggered by USARTz Rx event) Config */
DMA_DeInit(USARTz_Rx_DMA_Channel);
DMA_InitStructure.PeriphAddr = USARTz_DAT_Base;
DMA_InitStructure.MemAddr = (uint32_t)RxBuffer2;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = TxBufferSize1;
DMA_Init(USARTz_Rx_DMA_Channel, &DMA_InitStructure);
DMA_RequestRemap(USARTz_Rx_DMA_REMAP,USARTz_Rx_DMA_Channel,ENABLE);
3. 使能 DMA 请求与四个通道。 两路都打开 DMA 收发请求,四个通道一并使能,再启动两路 USART。
/* Enable USARTy DMA Rx and TX request */
USART_EnableDMA(USARTy, USART_DMAREQ_RX | USART_DMAREQ_TX,ENABLE);
/* Enable USARTz DMA Rx and TX request */
USART_EnableDMA(USARTz, USART_DMAREQ_RX | USART_DMAREQ_TX,ENABLE);
/* Enable USARTy TX DMA Channel */
DMA_EnableChannel(USARTy_Tx_DMA_Channel,ENABLE);
/* Enable USARTy RX DMA Channel */
DMA_EnableChannel(USARTy_Rx_DMA_Channel,ENABLE);
/* Enable USARTz TX DMA Channel */
DMA_EnableChannel(USARTz_Tx_DMA_Channel,ENABLE);
/* Enable USARTz RX DMA Channel */
DMA_EnableChannel(USARTz_Rx_DMA_Channel,ENABLE);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
4. 查询四路 DMA 是否传输完成。 依次等待四路通道的完成标志,再比较两组数据。
/* Wait until USARTy TX DMA Channel Transfer Complete */
while (DMA_GetFlagStatus(USARTy_Tx_DMA_FLAG,DMA1) == RESET)
{
}
/* Wait until USARTy RX DMA Channel Transfer Complete */
while (DMA_GetFlagStatus(USARTy_Rx_DMA_FLAG,DMA1) == RESET)
{
}
/* Wait until USARTz TX DMA Channel Transfer Complete */
while (DMA_GetFlagStatus(USARTz_Tx_DMA_FLAG,DMA1) == RESET)
{
}
/* Wait until USARTz RX DMA Channel Transfer Complete */
while (DMA_GetFlagStatus(USARTz_Rx_DMA_FLAG,DMA1) == RESET)
{
}
对应源码: src/main.c、inc/main.h、src/n32h49x_it.c
5.28.3.5 FIFO_Interrupt FIFO 中断收发
工程目录: projects/n32h49x_EVAL/examples/USART/FIFO_Interrupt/
初始化两路串口并打开 FIFO 模式→设置接收 FIFO 阈值并开启接收阈值中断→两路各自发送 16 字节数据→中断中按 FIFO 深度读出并比较收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)与 USARTz(UART5)互联,打开 FIFO 模式并把接收阈值设为 8,双方各发送 16 字节,接收端在中断中一次性读走整段 FIFO 数据后比对。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 与 NVIC 配置、FIFO 阈值与模式设置、数据发送与比对;inc/main.h:两路实例、引脚、复用号与中断向量宏;src/n32h49x_it.c:USART3 与 UART5 中断服务函数,按 FIFO 深度批量读取;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17、Rx PA15/GPIO_AF18),USARTz 为 UART5(Tx PA2/GPIO_AF20、Rx PA3/GPIO_AF21),复用推挽、上拉。波特率 9600、8 位字长、1 位停止位、无校验; 两路都设 USART_FIFO_DEEP8 接收阈值并开 USART_INT_RXFTE 中断,NVIC 分组 2、USART3 子优先级 0、UART5 子优先级 1。 |
| 程序与数据路径 | main 配置时钟、NVIC、GPIO 与两路 USART,设置接收 FIFO 阈值、打开 FIFO 模式、使能接收阈值中断,再逐字节发送两组 16 字节数据。发送过半时先等待对端已收到数据,最后等待收发计数到达 16,用 Buffercmp 比较两组缓冲区并写入 TransferStatus1 与 TransferStatus2。 |
| 主要 API | USART_Init、USART_CfgRxFIFOThreshold、USART_FIFOModeSet、USART_ConfigInt、USART_Enable、USART_SendData、USART_GetRxFIFO_Num、USART_ReceiveData |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Rx(PA3)、USART3_Rx(PA15)接 UART5_Tx(PA2),复位运行; 依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示两组数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;接收阈值中断触发后要按 USART_GetRxFIFO_Num 返回的深度循环读取,避免 FIFO 溢出;读完整段后仍需判读并清除溢出、噪声、校验与帧错误标志。 工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用接收阈值中断配合 FIFO,把整段数据一次读出,减少中断次数。
数据路径: TxBuffer1 与 TxBuffer2 → 两路发送 → 对端 FIFO → RXFTE 中断按 FIFO 深度读出 → RxBuffer1 与 RxBuffer2 → Buffercmp 比较
1. 打开 FIFO 模式并设置接收阈值与中断。 两路先设 8 级接收阈值并打开 FIFO 模式,再使能接收阈值中断,最后一起启动。
/* Set the RXFIFO threshold */
USART_CfgRxFIFOThreshold(USARTy,USART_FIFO_DEEP8);
USART_CfgRxFIFOThreshold(USARTz,USART_FIFO_DEEP8);
/* Enable the FIFO mode */
USART_FIFOModeSet(USARTy,ENABLE);
USART_FIFOModeSet(USARTz,ENABLE);
/* Enable USARTy Receive and Transmit interrupts */
USART_ConfigInt(USARTy, USART_INT_RXFTE,ENABLE);
/* Enable USARTz Receive and Transmit interrupts */
USART_ConfigInt(USARTz, USART_INT_RXFTE,ENABLE);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
2. 逐字节发送两组 16 字节数据。 中途在发送到第 8 字节时先等待对端已收到数据,避免 FIFO 溢出丢数据。
for(TxCounter1=0;TxCounter1<Buffer_Num;TxCounter1++)
{
/* wait USARTz Receive Completion Data,Otherwise it will lead to data loss */
if(TxCounter1 == 8)
{
while(RxBuffer2[TxCounter1-1] == 0);
}
/* Write one byte to the transmit data register */
USART_SendData(USARTy, TxBuffer1[TxCounter1]);
}
for(TxCounter2=0;TxCounter2<Buffer_Num;TxCounter2++)
{
/* wait USARTy Receive Completion Data,Otherwise it will lead to data loss */
if(TxCounter2 == 8)
{
while(RxBuffer1[TxCounter2-1] == 0);
}
/* Write one byte to the transmit data register */
USART_SendData(USARTz, TxBuffer2[TxCounter2]);
}
3. 中断中按 FIFO 深度批量读出。 接收阈值中断触发后先读 FIFO 内字节数,再按该数量循环读出。
void USARTy_IRQHandler(void)
{
uint32_t i,j;
if ((USART_GetFlagStatus(USARTy, USART_FLAG_RXFT) != RESET) && (USART_GetIntStatus(USARTy, USART_INT_RXFTE) != RESET))
{
j = USART_GetRxFIFO_Num(USARTy);
for(i=0;i<j;i++)
{
/* Read one byte from the receive data register */
RxBuffer1[RxCounter1++] = USART_ReceiveData(USARTy);
}
}
对应源码: src/main.c、inc/main.h、src/n32h49x_it.c
5.28.3.6 HalfDuplex 半双工收发
工程目录: projects/n32h49x_EVAL/examples/USART/HalfDuplex/
初始化两路串口并开启半双工模式→单线互联上 USART3 发 UART5 收→反向由 UART5 发 USART3 收→比较两组收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)与 USARTz(UART5)各以一根 Tx 引脚单线互联,开启半双工模式后分时收发,再比对两组数据。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 配置、半双工使能、分时收发与数据比对;inc/main.h:两路实例、引脚、复用号与测试状态枚举;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17),USARTz 为 UART5(Tx PA7/GPIO_AF20),复用推挽、上拉;只连 Tx 一线,半双工下该引脚兼作收发端。 波特率 9600、8 位字长、1 位停止位、无校验,两路都调用 USART_EnableHalfDuplex 打开半双工。 |
| 程序与数据路径 | main 配置时钟、GPIO 与两路 USART,启动两路并开启半双工,先由 USART3 逐字节发到 UART5 存入 RxBuffer2。再由 UART5 逐字节发到 USART3 存入 RxBuffer1,期间靠收发标志确认每字节完成,最后用 Buffercmp 比较两组缓冲区。 |
| 主要 API | USART_Init、USART_Enable、USART_EnableHalfDuplex、USART_SendData、USART_ReceiveData、USART_GetFlagStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Tx(PA7),复位运行; 依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示两组数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;半双工只用一根数据线,收发必须分时进行,不能同时启动双向传输。 工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例把两路串口各设为一根 Tx 线,开启半双工后分时收发,并逐字节确认。
数据路径: TxBuffer1 → USART3 单线发送 → UART5 → RxBuffer2;TxBuffer2 → UART5 单线发送 → USART3 → RxBuffer1 → Buffercmp 比较
1. 初始化两路并开启半双工。 两路串口参数一致,启动后再分别打开半双工模式。
/* Configure USARTy and USARTz */
USART_Init(USARTy, &USART_InitStructure);
USART_Init(USARTz, &USART_InitStructure);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
/* Enable USARTy Half Duplex Mode*/
USART_EnableHalfDuplex(USARTy,ENABLE);
/* Enable USARTz Half Duplex Mode*/
USART_EnableHalfDuplex(USARTz,ENABLE);
2. USART3 发、UART5 收。 先等发送寄存器空再写入,再等对端收到并读走数据;读前判读溢出标志。
while (NbrOfDataToRead2--)
{
/* Wait until end of transmit */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
{
}
/* Write one byte in the USARTy Transmit Data Register */
USART_SendData(USARTy, TxBuffer1[TxCounter1++]);
/* Wait the byte is entirely received by USARTz */
while (USART_GetFlagStatus(USARTz, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTz, USART_FLAG_OREF) != RESET)
{
USARTz->DAT;
}
}
/* Store the received byte in the RxBuffer2 */
RxBuffer2[RxCounter2++] = USART_ReceiveData(USARTz);
}
3. UART5 发、USART3 收。 反向过程与上一段对称,收发完成后同样以标志确认。
while (NbrOfDataToRead1--)
{
/* Wait until end of transmit */
while (USART_GetFlagStatus(USARTz, USART_FLAG_TXDE) == RESET)
{
}
/* Write one byte in the USARTz Transmit Data Register */
USART_SendData(USARTz, TxBuffer2[TxCounter2++]);
/* Wait the byte is entirely received by USARTy */
while (USART_GetFlagStatus(USARTy, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTy, USART_FLAG_OREF) != RESET)
{
USARTy->DAT;
}
}
/* Store the received byte in the RxBuffer1 */
RxBuffer1[RxCounter1++] = USART_ReceiveData(USARTy);
}
对应源码: src/main.c、inc/main.h
5.28.3.7 HardwareFlowCtrl 硬件流控收发
工程目录: projects/n32h49x_EVAL/examples/USART/HardwareFlowCtrl/
初始化两路串口并使能 RTS/CTS 硬件流控→USART1 经 CTS 发送、USART2 经 RTS 接收→反向由 USART2 发送、USART1 接收→比较两组收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART1)与 USARTz(USART2)四线互联,打开 RTS/CTS 硬件流控后双向收发,再比对两组数据。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 配置、流控参数、双向收发与数据比对;inc/main.h:两路实例、数据与流控引脚、复用号与测试状态枚举;readme.txt:功能、环境、四线连接与测试步骤。 |
| 关键配置 | USARTy 为 USART1(Tx PA9、Rx PA10、RTS PA12、CTS PA11,复用 GPIO_AF5),USARTz 为 USART2(Tx PA2、Rx PA3、RTS PA1、CTS PA0)。波特率 115200、8 位字长、1 位停止位、无校验; HardwareFlowControl 同时打开 USART_HFCTRL_CTS 与 USART_HFCTRL_RTS,RTS 配为推挽输出、CTS 配为带上拉输入。 |
| 程序与数据路径 | main 配置时钟、GPIO 与两路 USART 并启动,先由 USART1 逐字节发送、USART2 接收存入 RxBuffer2。再由 USART2 逐字节发送、USART1 接收存入 RxBuffer1,期间以发送空与接收非空标志同步,最后用 Buffercmp 比较两组缓冲区。 |
| 主要 API | USART_Init、USART_Enable、USART_SendData、USART_ReceiveData、USART_GetFlagStatus |
| 验证方法 | 按 Tx 对 Rx、CTS 对 RTS 交叉接通 PA9/PA3、PA10/PA2、PA11/PA1、PA12/PA0,复位运行; 依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示两组数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;发送端使能 CTS、接收端使能 RTS,两端的流量控制引脚必须交叉对接才能生效。 工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用 RTS/CTS 四线把两路串口对接,双向收发时由硬件流控信号控制节奏。
数据路径: TxBuffer1 → USART1(CTS 流控)→ USART2(RTS 流控)→ RxBuffer2;TxBuffer2 → USART2 → USART1 → RxBuffer1 → Buffercmp 比较
1. 在初始化参数里同时使能 CTS 与 RTS。 两路共用一份参数,流控字段把发送与接收两侧都打开。
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_CTS | USART_HFCTRL_RTS;
USART_InitStructure.OverSampling = USART_16OVER;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTy and USARTz */
USART_Init(USARTy, &USART_InitStructure);
USART_Init(USARTz, &USART_InitStructure);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
2. 把 RTS 配为推挽输出、CTS 配为带上拉输入。 流控信号一个对外输出、一个对内采样,方向不能配反。
/* Configure USARTy RTS as alternate function push-pull */
GPIO_InitStructure.Pin = USARTy_RTSPin;
GPIO_InitStructure.GPIO_Alternate = USARTy_RTS_GPIO_AF;
GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);
/* Configure USARTz Tx as alternate function push-pull */
GPIO_InitStructure.Pin = USARTz_TxPin;
GPIO_InitStructure.GPIO_Alternate = USARTz_Tx_GPIO_AF;
GPIO_InitPeripheral(USARTz_GPIO, &GPIO_InitStructure);
/* Configure USARTz RTS as alternate function push-pull */
GPIO_InitStructure.Pin = USARTz_RTSPin;
GPIO_InitStructure.GPIO_Alternate = USARTz_RTS_GPIO_AF;
GPIO_InitPeripheral(USARTz_GPIO, &GPIO_InitStructure);
/* Configure USARTy Rx as alternate function input and pull-up */
GPIO_InitStructure.Pin = USARTy_RxPin;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_InitStructure.GPIO_Alternate = USARTy_Rx_GPIO_AF;
GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);
/* Configure USARTz Rx as alternate function input and pull-up */
GPIO_InitStructure.Pin = USARTz_RxPin;
GPIO_InitStructure.GPIO_Alternate = USARTz_Rx_GPIO_AF;
GPIO_InitPeripheral(USARTz_GPIO, &GPIO_InitStructure);
/* Configure USARTy CTS as alternate function input and pull-up */
GPIO_InitStructure.Pin = USARTy_CTSPin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_InitStructure.GPIO_Alternate = USARTy_CTS_GPIO_AF;
GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);
/* Configure USARTz CTS as alternate function input and pull-up */
GPIO_InitStructure.Pin = USARTz_CTSPin;
GPIO_InitStructure.GPIO_Alternate = USARTz_CTS_GPIO_AF;
GPIO_InitPeripheral(USARTz_GPIO, &GPIO_InitStructure);
3. 逐字节双向收发并同步。 每发一字节先等发送寄存器空,再等对端收到并读走;反向过程与之对称。
while (NbrOfDataToRead2--)
{
/* Send one byte from USARTy to USARTz */
USART_SendData(USARTy, TxBuffer1[TxCounter1++]);
/* Loop until USARTy DAT register is empty */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
{
}
/* Loop until the USARTz Receive Data Register is not empty */
while (USART_GetFlagStatus(USARTz, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTz, USART_FLAG_OREF) != RESET)
{
USARTz->DAT;
}
}
/* Store the received byte in RxBuffer */
RxBuffer2[RxCounter2++] = USART_ReceiveData(USARTz);
}
while (NbrOfDataToRead1--)
{
/* Send one byte from USARTy to USARTz */
USART_SendData(USARTz, TxBuffer2[TxCounter2++]);
/* Loop until USARTz DAT register is empty */
while (USART_GetFlagStatus(USARTz, USART_FLAG_TXDE) == RESET)
{
}
/* Loop until the USARTz Receive Data Register is not empty */
while (USART_GetFlagStatus(USARTy, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTy, USART_FLAG_OREF) != RESET)
{
USARTy->DAT;
}
}
/* Store the received byte in RxBuffer */
RxBuffer1[RxCounter1++] = USART_ReceiveData(USARTy);
}
对应源码: src/main.c、inc/main.h
5.28.3.8 Interrupt 中断收发
工程目录: projects/n32h49x_EVAL/examples/USART/Interrupt/
初始化两路串口并打开收发中断→中断中逐字节发送并接收数据→收满后关闭该方向中断→比较两组收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)与 USARTz(UART5)互联,收发全部由中断驱动,某一方向收发到额定长度后关闭该方向中断,再比对两组数据。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 与 NVIC 配置、中断使能与数据比对;inc/main.h:两路实例、引脚、复用号与中断向量宏;src/n32h49x_it.c:USART3 与 UART5 中断服务函数,收发满额后关闭自身中断;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17、Rx PA15/GPIO_AF18),USARTz 为 UART5(Tx PA2/GPIO_AF20、Rx PA3/GPIO_AF21),复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验; 两路都开 USART_INT_RXDNE 与 USART_INT_TXDE 中断,NVIC 分组 2、USART3 子优先级 0、UART5 子优先级 1。 |
| 程序与数据路径 | main 配置时钟、NVIC、GPIO 与两路 USART,使能收发中断后启动两路,随后等待两个方向接收计数达到额定长度。发满或收满时在中断里关闭本方向中断以免反复触发,主循环最后用 Buffercmp 比较两组缓冲区并写入 TransferStatus1 与 TransferStatus2。 |
| 主要 API | USART_Init、USART_ConfigInt、USART_Enable、USART_SendData、USART_ReceiveData、USART_GetFlagStatus、USART_GetIntStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Rx(PA3)、USART3_Rx(PA15)接 UART5_Tx(PA2),复位运行; 依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示两组数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;发送和接收都在中断里完成,收发满额后要关闭对应中断,避免条件持续为真反复进出中断; 接收分支同样要判读并清除溢出、噪声、校验与帧错误标志。 工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例把发送和接收都放进中断,收满即关闭本方向中断,主循环只做结果比对。
数据路径: TxBuffer1 与 TxBuffer2 → 中断逐字节发送 → 对端中断逐字节接收 → RxBuffer1 与 RxBuffer2 → Buffercmp 比较
1. 使能两路的收发中断并启动。 接收非空与发送空各开一个中断源,两路都打开后再启动串口。
/* Enable USARTy Receive and Transmit interrupts */
USART_ConfigInt(USARTy, USART_INT_RXDNE,ENABLE);
USART_ConfigInt(USARTy, USART_INT_TXDE,ENABLE);
/* Enable USARTz Receive and Transmit interrupts */
USART_ConfigInt(USARTz, USART_INT_RXDNE,ENABLE);
USART_ConfigInt(USARTz, USART_INT_TXDE,ENABLE);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
2. 中断里收发并在满额后关闭本方向中断。 先判读标志与中断使能位,收或发到额定长度就关掉相应中断。
void USARTy_IRQHandler(void)
{
if ((USART_GetFlagStatus(USARTy, USART_FLAG_RXDNE) != RESET) && (USART_GetIntStatus(USARTy, USART_INT_RXDNE) != RESET))
{
/* Read one byte from the receive data register */
RxBuffer1[RxCounter1++] = USART_ReceiveData(USARTy);
if (RxCounter1 == NbrOfDataToRead1)
{
/* Disable the USARTy Receive interrupt */
USART_ConfigInt(USARTy, USART_INT_RXDNE,DISABLE);
}
}
if ((USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) != RESET) && (USART_GetIntStatus(USARTy, USART_INT_TXDE) != RESET))
{
/* Write one byte to the transmit data register */
USART_SendData(USARTy, TxBuffer1[TxCounter1++]);
if (TxCounter1 == NbrOfDataToTransfer1)
{
/* Disable the USARTy Transmit interrupt */
USART_ConfigInt(USARTy, USART_INT_TXDE,DISABLE);
}
}
3. 主循环等收满后比较结果。 两个方向各自等到接收计数达到额定长度,再分别比对收发缓冲区。
/* Wait until end of transmission from USARTy to USARTz */
while (RxCounter2 < RxBufferSize2)
{
}
/* Wait until end of transmission from USARTz to USARTy */
while (RxCounter1 < RxBufferSize1)
{
}
/* Check the received data with the send ones */
TransferStatus1 = Buffercmp(TxBuffer1, RxBuffer2, TxBufferSize1);
对应源码: src/main.c、inc/main.h、src/n32h49x_it.c
5.28.3.9 Transmit_Receive 红外收发
工程目录: projects/n32h49x_EVAL/examples/USART/IrDA_Tx&Rx/Transmit_Receive/
初始化两路串口并打开低功耗 IrDA 模式→由定时器输出 38kHz 载波驱动红外发射管→USART3 经红外发送、UART5 中断接收→比较收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)发送、USARTz(UART5)接收,工作在串行 IrDA 低功耗模式,两端经红外发射器与接收器完成红外解码通信后比对数据。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 与 NVIC 配置、IrDA 模式与预分频设置、发送与比对;inc/main.h:两路实例、引脚、复用号与中断向量宏;src/bsp_Tim_38K.c 与 inc/bsp_Tim_38K.h:输出 38kHz 载波;src/n32h49x_it.c:UART5 接收中断服务函数;readme.txt:功能、环境、引脚连接与注意事项。 |
| 关键配置 | USARTy 为 USART3(Tx PA4/GPIO_AF17),USARTz 为 UART5(Rx PG3/GPIO_AF21),另用 PA8 输出 38kHz 载波。波特率 1200、8 位字长、1 位停止位、无校验; 两路预分频器都设为 0x01,IrDA 模式为 USART_IRDAMODE_NORMAL,并把 APB1 时钟降低以匹配低波特率。 |
| 程序与数据路径 | main 配置时钟、NVIC、GPIO 与 38kHz 载波,USART3 配成发送、UART5 配成接收,设置预分频与 IrDA 模式后使能。USART3 逐字节发出整串数据,UART5 在中断中逐字节接收存入 RxBuffer1,主循环等收满后用 Buffercmp 比较并写入 TransferStatus。 |
| 主要 API | USART_Init、USART_SetPrescaler、USART_ConfigIrDAMode、USART_EnableIrDA、USART_ConfigInt、USART_Enable、USART_SendData |
| 验证方法 | 在开发板上接好红外发射器与接收器,复位运行; 查看 TransferStatus,为 PASSED 表示接收数据与发送数据一致。 |
| 使用提示 | 需先连接跳线帽 J87、J89; 低功耗 IrDA 需要 38kHz 载波配合,且要降低 APB 时钟才能产生 1200 波特的低速时钟; 工程基于全功能板 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用一路串口发、一路串口收,配合 38kHz 载波完成低功耗 IrDA 红外通信。
数据路径: TxBuffer1 → USART3(IrDA 发送)→ 红外发射器 → 红外接收器 → UART5(IrDA 接收)→ RxBuffer1 → Buffercmp 比较
1. 一路配成发送、一路配成接收。 两路参数一致,只把工作模式分别设成发送与接收,并打开 UART5 的接收中断。
USART_InitStructure.BaudRate = 1200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.OverSampling = USART_16OVER;
USART_InitStructure.Mode = USART_MODE_TX;
/* Configure USARTy and USARTz */
USART_Init(USARTy, &USART_InitStructure);
USART_InitStructure.Mode = USART_MODE_RX;
USART_Init(USARTz, &USART_InitStructure);
/* Enable USARTz Receive interrupts */
USART_ConfigInt(USARTz, USART_INT_RXDNE,ENABLE);
2. 设置预分频与 IrDA 模式并使能。 低功耗 IrDA 需要预分频器把时钟降到合适频率,配好模式后再一起使能。
/* Set the USARTy prescaler */
USART_SetPrescaler(USARTy, 0x01);//>219
USART_SetPrescaler(USARTz, 0x01);
/* Configure the USARTy IrDA mode */
USART_ConfigIrDAMode(USARTy, USART_IRDAMODE_NORMAL);
USART_ConfigIrDAMode(USARTz, USART_IRDAMODE_NORMAL);
/* Enable the USARTy IrDA mode */
USART_EnableIrDA(USARTy,ENABLE);
USART_EnableIrDA(USARTz,ENABLE);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy,ENABLE);
USART_Enable(USARTz,ENABLE);
3. 逐字节发送并等待接收完成。 发送侧每写一字节就等发送寄存器空,主循环再等接收计数收满。
while (TxCounter < TxBufferSize1)
{
/* Send one byte from Board1_USARTy to Board2_USARTz */
USART_SendData(USARTy, TxBuffer1[TxCounter++]);
/* Loop until Board1_USARTy DAT register is empty */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
{
}
}
while (RxCounter < TxBufferSize1)
{
}
对应源码: src/main.c、inc/main.h、src/bsp_Tim_38K.c、src/n32h49x_it.c
5.28.3.10 LIN_Master LIN 主机
工程目录: projects/n32h49x_EVAL/examples/USART/LIN/LIN_Master/
初始化 UART5 的 LIN 模式并设断帧检测长度→主节点轮询发送 0x3C 主请求帧→发送 0x3D 从应答帧头并等待从机回复→校验并打印 8 字节回复数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTx(UART5)工作在 LIN 主节点模式,轮询发送主请求帧(0x3C)与从机应答帧头(0x3D),并在收到从机 8 字节回复后打印。 |
| 源码组成 | src/main.c:时钟、NVIC、GPIO 与 LIN 模式初始化,主循环轮询调用测试流程;src/lin_master.c:帧头校验码计算、字节收发、请求帧与应答帧流程;inc/lin_master.h、inc/main.h:报文结构体、函数声明与实例宏;readme.txt:功能、环境、双板连接与测试步骤。 |
| 关键配置 | USARTx 为 UART5(Tx PG2/GPIO_AF20、Rx PG3/GPIO_AF21),复用推挽、上拉;打印口为 PA9/PA10、波特率 115200。 LIN 波特率 9600、8 位字长、1 位停止位、无校验,断帧检测长度设为 USART_LINBDL_10B 并使能 LIN 模式。 |
| 程序与数据路径 | main 配置时钟、NVIC、GPIO 与 UART5,设置断帧检测长度、打开 LIN 模式与串口后进入死循环。TestMasterReqFrame 发出 0x3C 请求帧并附 8 字节 0x0F,TestSlaveResFrame 发出 0x3D 帧头,WaitFrameRes 校验从机回复后把数据拷回并打印。 |
| 主要 API | USART_Init、USART_ConfigLINBreakDetectLength、USART_EnableLIN、USART_Enable、USART_SendBreak、USART_SendData、USART_GetFlagStatus |
| 验证方法 | 两块板分别烧录 LIN_Master 与 LIN_Slave,先复位从机再复位主机,按 readme 连接 PG2 与 PA5、PG3 与 PA4 并共地; 在打印口查看主机依次发出请求帧与应答帧头,并打印从机回复的 8 字节数据。 |
| 使用提示 | 主从两板必须共地,且主机 Tx 接从机 Rx、主机 Rx 接从机 Tx; LIN 帧以 USART_SendBreak 产生同步断帧作起点,主节点负责提供帧头、从节点只回数据。工程基于全功能板 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
主节点负责发帧头并轮询等待从机应答,帧头校验与数据校验都由软件按 LIN 规则计算。
数据路径: 请求帧(0x3C,8 字节 0x0F)→ LIN 总线 → 从机;应答帧头(0x3D)→ 从机回复 8 字节 → 校验和比对 → 打印
1. 设置断帧检测长度并打开 LIN 模式。 参数按 9600 波特率配置,先设断帧检测长度,再打开 LIN 模式与串口。
USART_InitStructure.BaudRate = 9600;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx LIN mode*/
USART_ConfigLINBreakDetectLength(USARTx,USART_LINBDL_10B);
USART_EnableLIN(USARTx,ENABLE);
/* Enable the USARTx */
USART_Enable(USARTx,ENABLE);
2. 发断帧后逐字节发送帧内容。 每个 LIN 帧都先由发送断帧产生同步头,再等发送完成后写入每个字节。
void MasterSendBytes(uint8_t *pBuf, uint8_t Len)
{
USART_SendBreak(USARTx);
while(Len--)
{
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXC) == RESET);
USART_SendData(USARTx, *pBuf++);
}
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXC ) == RESET);
}
3. 主循环比较请求帧与应答帧。 先发 0x3C 请求帧,隔一小段时间后发 0x3D 帧头,最多重试四次等待从机回复。
void TestLinMaster(void)
{
int i = 0, count = 0;
uint8_t recv_data[8];
TestMasterReqFrame();
systick_delay_ms(20);
while(count < 4)
{
Memset(recv_data, 0, 8);
TestSlaveResFrame();
if(WaitFrameRes(recv_data, 8) == SUCCESS)
{
log_info("recv_data:\r\n");
for(i = 0; i < 8; i++)
{
log_info("recv_data[%d] = 0x%x\r\n", i, recv_data[i]);
}
break;
}
else
{
log_info("slave no response!!\r\n");
count++;
}
}
}
对应源码: src/main.c、src/lin_master.c、inc/lin_master.h
5.28.3.11 LIN_Slave LIN 从机
工程目录: projects/n32h49x_EVAL/examples/USART/LIN/LIN_Slave/
初始化 UART5 的 LIN 模式并区分接收与发送 ID→中断中按断帧与状态机接收主机请求帧→应用层回填 8 字节应答数据→从机把应答数据回发主机
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTx(UART5)工作在 LIN 从节点模式,用状态机在中断中解析主机帧头,收到请求帧后由应用层回填数据并向主机发出 8 字节应答。 |
| 源码组成 | src/main.c:时钟、NVIC、GPIO、LIN 与中断配置,主循环处理已收到的报文;src/lin_slave.c:断帧与状态机接收、校验码计算、应答数据组帧与回发;inc/lin_slave.h、inc/main.h:状态枚举、报文结构体与实例宏;readme.txt:功能、环境、双板连接与测试步骤。 |
| 关键配置 | USARTx 为 UART5(Tx PA4/GPIO_AF20、Rx PA5/GPIO_AF21),复用推挽、上拉;打印口为 PA9/PA10、波特率 115200。 LIN 波特率 9600、8 位字长、1 位停止位、无校验,断帧检测长度 USART_LINBDL_10B,并开 USART_INT_RXDNE 与 USART_INT_LINBD 两个中断。 |
| 程序与数据路径 | main 配置时钟、NVIC、GPIO 与 UART5,打开 LIN 模式与收发、断帧中断后启动,再按 ID 把接收与发送 ID 分别标记为从机接收帧与从机应答帧。中断里 LIN 状态机依次经历同步、ID、取数、校验四步,收满后置位 GotMsgFlag; 主循环据此调用 BOOT_ExecutiveCommand 把 8 字节应答数据交给回发函数。 |
| 主要 API | USART_Init、USART_ConfigLINBreakDetectLength、USART_EnableLIN、USART_ConfigInt、USART_Enable、USART_ClrFlag、USART_SendData、USART_ReceiveData |
| 验证方法 | 两块板分别烧录 LIN_Master 与 LIN_Slave,先复位从机再复位主机,按 readme 连接 PG2 与 PA5、PG3 与 PA4 并共地; 从机侧可看到解析过程与回填数据的打印,主机侧打印出收到的 8 字节应答。 |
| 使用提示 | 主从两板必须共地,且主机 Tx 接从机 Rx、主机 Rx 接从机 Tx; 从机必须在断帧中断里清 LINBD 标志并读一次寄存器清帧错误,否则状态机不会重新进入同步; 同一 ID 只应配置为接收或发送一种方向。 工程基于全功能板 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
从节点不在主循环里收数据,而是靠断帧中断启动状态机,收满后交给应用层组帧回发。
数据路径: 主机帧头 → LINBD 与接收中断 → LIN_EX_RxAsync 状态机 → LINRxDataBuffer → GotMsgFlag → BOOT_ExecutiveCommand → LIN_SetResp → LIN_SendBytes
1. 打开 LIN 模式与接收、断帧中断。 参数按 9600 波特率配置,断帧检测长度设为 10 位,中断使能后再启动串口。
USART_InitStructure.BaudRate = 9600;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx LIN mode*/
USART_ConfigLINBreakDetectLength(USARTx,USART_LINBDL_10B);
USART_EnableLIN(USARTx,ENABLE);
/* Enable USARTx Receive and Transmit interrupts */
USART_ConfigInt(USARTx, USART_INT_RXDNE,ENABLE);
USART_ConfigInt(USARTx, USART_INT_LINBD,ENABLE);
2. 断帧中断启动同步、接收中断推送数据。 检测到 LIN 断帧就清标志并让状态机进入同步,之后每收到一字节就送进状态机。
void LIN_IRQHandler(void)
{
if(USART_GetFlagStatus(USARTx, USART_FLAG_LINBD) == SET)
{
USART_ClrFlag(USARTx, USART_FLAG_LINBD);//Clear the LIN interval field detection flag bit
//Read the status register and data register and clear the FE flag
USARTx->STS;
USARTx->DAT;
LinRxState = SYNCH;
return;
}
if (USART_GetFlagStatus(USARTx, USART_FLAG_RXDNE) == SET)
{
USART_ClrFlag(USARTx, USART_FLAG_RXDNE); //Clear the receive interrupt flag bit
if(USART_GetFlagStatus(USARTx, USART_FLAG_FEF) == RESET)
{
LIN_EX_RxAsync((uint8_t)USART_ReceiveData(USARTx));
}
}
3. 状态机按同步、ID 两步解析帧头。 同步字节必须是 0x55,ID 通过校验位后,按该 ID 的收发方向决定取数还是回发。
void LIN_EX_RxAsync(uint8_t data)
{
switch(LinRxState)
{
case IDLE:
break;
case SYNCH:
if(data == 0x55)
{
LINRxDataBuffer[LINRxDataIndex].Sync = 0x55;
LinRxState = ID_LEN;
}
else
{
LinRxState = IDLE;
}
break;
case ID_LEN:
if(GET_PID(data) == data)
{
LINRxDataBuffer[LINRxDataIndex].PID = data;
LINRxDataBuffer[LINRxDataIndex].DataLen = 0;
if(IDType[data & 0x3F] == ID_TYPE_SR)
{
LinRxState = DATA_GET;
}
else
{
//Receives the frame header sent by the host and sends data in slave mode
if(((LINTxMsg.PID & 0x3F) == (data & 0x3F)) && (LINTxMsg.DataLen > 0))
{
LIN_SendBytes(LINTxMsg.Data, LINTxMsg.DataLen + 1);
LINTxMsg.DataLen = 0;
}
LinRxState = IDLE;
}
}
else
{
LinRxState = IDLE;
}
break;
4. 主循环把收到的帧交给应用层回填并回发。 状态机收满整帧后置位标志,主循环据此执行应用逻辑并清标志。
while (1)
{
if(GotMsgFlag)
{
BOOT_ExecutiveCommand(pLINMsg->Data, LIN_RespData);
GotMsgFlag = 0;
}
}
对应源码: src/main.c、src/lin_slave.c、inc/lin_slave.h
5.28.3.12 MultiProcessor 多处理器模式
工程目录: projects/n32h49x_EVAL/examples/USART/MultiProcessor/
初始化两路串口并分别设置本机地址→从机静默接收、主机持续发送 0x33→按键触发从机进入静默模式→主机发送地址帧把从机唤醒恢复接收
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)持续向 USARTz(UART5)发送 0x33,从机收到即翻转 LED1;按键经外部中断让从机进入静默,再由主机发地址 0x102 唤醒。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 配置、地址与唤醒方式设置、查询收发与 LED 翻转;src/bsp_led.c、src/bsp_key.c 与对应头文件:板载 LED 与按键初始化;src/n32h49x_it.c:EXTI15_10 中断服务函数,切换静默与唤醒;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17、Rx PA15/GPIO_AF18),USARTz 为 UART5(Tx PA2/GPIO_AF20、Rx PA3/GPIO_AF21);LED1 用 PA8,按键用 PC13 并开外部中断。 波特率 115200、9 位字长、1 位停止位、无校验; 两路地址分别设为 0x1 与 0x2,唤醒方式为 USART_WUM_ADDRMASK。 |
| 程序与数据路径 | main 配置时钟、GPIO、LED 与按键,初始化两路并启动,设置地址和唤醒方式后进入死循环。循环里主机不断发 0x33,从机收到就翻转 LED1; 按键中断中先让从机开静默、再让主机发地址 0x102 将其唤醒。 |
| 主要 API | USART_Init、USART_Enable、USART_SetAddr、USART_ConfigWakeUpMode、USART_EnableRcvWakeUp、USART_SendData、USART_ReceiveData、USART_GetFlagStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Rx(PA3)、USART3_Rx(PA15)接 UART5_Tx(PA2),复位运行; 观察 LED1 持续闪烁,按一次按键停止闪烁,再按一次恢复闪烁。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;从机进入静默后不再接收普通数据,只有匹配本机地址的地址帧才能唤醒它; 多处理器模式要求数据字长为 9 位,第 9 位用于区分地址帧与数据帧。 工程基于全功能板 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
多处理器模式用 9 位字长区分地址与数据,从机静默后靠地址帧被唤醒。
数据路径: 主机 0x33 → 从机校验并翻转 LED1;按键 EXTI → 从机开启静默 → 主机发送地址 0x102 → 从机唤醒
1. 设置两路地址与从机唤醒方式。 两路都用 9 位字长,各自设置本机地址,从机再选择按地址掩码唤醒。
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_9B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.OverSampling = USART_16OVER;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTy and USARTz */
USART_Init(USARTy, &USART_InitStructure);
USART_Init(USARTz, &USART_InitStructure);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
/* Set the USARTy and USARTz Address */
USART_SetAddr(USARTy, 0x1);
USART_SetAddr(USARTz, 0x2);
/* Select the USARTz WakeUp Method */
USART_ConfigWakeUpMode(USARTz, USART_WUM_ADDRMASK);
2. 查询收发并按收到的数据翻转 LED。 主机不断发 0x33,从机收到相同数据就点亮再熄灭 LED1,形成闪烁。
while (1)
{
/* Send one byte from USARTy to USARTz */
USART_SendData(USARTy, 0x33);
/* Wait while USARTy TXE = 0 */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
{
}
if (USART_GetFlagStatus(USARTz, USART_FLAG_RXDNE) != RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTz, USART_FLAG_OREF) != RESET)
{
USARTz->DAT;
}
if (USART_ReceiveData(USARTz) == 0x33)
{
LED1_RED_ON;
Delay(0x1FFFFF);
LED1_RED_OFF;
Delay(0x1FFFFF);
}
}
}
3. 按键中断里先静默再发地址唤醒。 中断按标志位分两步:先把从机置入静默,延时后由主机发地址帧把它唤醒。
void EXTI15_10_IRQHandler(void)
{
Delay(0x2FFFFF);
if (ControlFlag == 2)
{
ControlFlag = 0;
}
if (ControlFlag == 0)
{
/* Flush DAT register and clear the USARTz RXNE flag */
USART_ReceiveData(USARTz);
/* Enable the USARTz mute mode*/
USART_EnableRcvWakeUp(USARTz,ENABLE);
ControlFlag = 1;
}
else if (ControlFlag == 1)
{
/* Send the address mark (0x102) to wakeup USARTz */
USART_SendData(USARTy, 0x102);
/* Wait while USARTy TXE = 0 */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
{
}
ControlFlag = 2;
}
/* Clear Key Button EXTI Line Pending Bit */
EXTI_ClrITPendBit(KEY_INPUT_EXTI_LINE);
}
对应源码: src/main.c、src/n32h49x_it.c、src/bsp_led.c、src/bsp_key.c
5.28.3.13 Polling 查询收发
工程目录: projects/n32h49x_EVAL/examples/USART/Polling/
初始化两路串口→USART3 查询发送、UART5 查询接收→反向由 UART5 查询发送、USART3 接收→两个方向分别比较收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART3)与 USARTz(UART5)互联,收发全部用标志查询完成,两个方向各比对一次数据。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 配置、标志查询收发与两次数据比对;inc/main.h:两路实例、引脚、复用号与测试状态枚举;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTy 为 USART3(Tx PA9/GPIO_AF17、Rx PA15/GPIO_AF18),USARTz 为 UART5(Tx PA2/GPIO_AF20、Rx PA3/GPIO_AF21),复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验,不用中断与 DMA,两个方向都用 USART_FLAG_TXDE 与 USART_FLAG_RXDNE 同步。 |
| 程序与数据路径 | main 配置时钟、GPIO 与两路 USART 并启动,先由 USART3 逐字节发到 UART5 存入 RxBuffer1,比较结果写入 TransferStatus。再把收发计数清零、状态置为失败,由 UART5 逐字节发到 USART3 存入 RxBuffer2,比较后再次写入同一个 TransferStatus。 |
| 主要 API | USART_Init、USART_Enable、USART_SendData、USART_ReceiveData、USART_GetFlagStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 UART5_Rx(PA3)、USART3_Rx(PA15)接 UART5_Tx(PA2),复位运行; 两次查看 TransferStatus(两个方向各一次),均为 PASSED 表示该方向数据收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;两个方向的比较结果共用同一个 TransferStatus,要在两个方向之间分别查看,否则只能看到后一次的结果。工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用最基础的标志查询完成双向收发,每发一字节都等发送寄存器空、每收一字节都等接收寄存器非空。
数据路径: TxBuffer1 → USART3 → UART5 → RxBuffer1 → Buffercmp 比较;TxBuffer2 → UART5 → USART3 → RxBuffer2 → Buffercmp 比较
1. 初始化两路并启动。 参数按 115200 波特率配置,两路共用一份结构体,配置完一起启动。
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.OverSampling = USART_16OVER;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTy and USARTz */
USART_Init(USARTy, &USART_InitStructure);
USART_Init(USARTz, &USART_InitStructure);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy, ENABLE);
USART_Enable(USARTz, ENABLE);
2. USART3 发、UART5 收后比较。 发完一字节等发送空,再等对端收到并读走,最后一个比较得出结果。
while (TxCounter < TxBufferSize1)
{
/* Send one byte from USARTy to USARTz */
USART_SendData(USARTy, TxBuffer1[TxCounter++]);
/* Loop until USARTy DAT register is empty */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
{
}
/* Loop until the USARTz Receive Data Register is not empty */
while (USART_GetFlagStatus(USARTz, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTz, USART_FLAG_OREF) != RESET)
{
USARTz->DAT;
}
}
/* Store the received byte in RxBuffer */
RxBuffer1[RxCounter++] = USART_ReceiveData(USARTz);
}
/* Check the received data with the send ones */
/* TransferStatus = PASSED, if the data transmitted from USARTy and
received by USARTz are the same */
/* TransferStatus = FAILED, if the data transmitted from USARTy and
received by USARTz are different */
TransferStatus = Buffercmp(TxBuffer1, RxBuffer1, TxBufferSize1);
3. 反向收发前先清零计数与状态。 计数与状态都要复位,反向收发流程与正向完全对称,比较结果复用同一个变量。
TxCounter = 0;
RxCounter = 0;
TransferStatus = FAILED;
while (TxCounter < TxBufferSize1)
{
/* Send one byte from USARTz to USARTy */
USART_SendData(USARTz, TxBuffer2[TxCounter++]);
/* Loop until USARTz DAT register is empty */
while (USART_GetFlagStatus(USARTz, USART_FLAG_TXDE) == RESET)
{
}
/* Loop until the USARTy Receive Data Register is not empty */
while (USART_GetFlagStatus(USARTy, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTy, USART_FLAG_OREF) != RESET)
{
USARTy->DAT;
}
}
/* Store the received byte in RxBuffer */
RxBuffer2[RxCounter++] = USART_ReceiveData(USARTy);
}
/* Check the received data with the send ones */
/* TransferStatus = PASSED, if the data transmitted from USARTz and
received by USARTy are the same */
/* TransferStatus = FAILED, if the data transmitted from USARTz and
received by USARTy are different */
TransferStatus = Buffercmp(TxBuffer2, RxBuffer2, TxBufferSize2);
对应源码: src/main.c、inc/main.h
5.28.3.14 Printf 串口打印
工程目录: projects/n32h49x_EVAL/examples/USART/Printf/
初始化 USART3 并配好发送引脚→把 C 库 printf 重定向到串口→复位后向 PC 终端打印一行提示→主循环空转等待
| 项目 | 源码解读 |
|---|---|
| 功能 | 把 C 库的 printf 重定向到 USARTx(USART3),启动后向 PC 终端打印一行提示信息,演示串口打印输出。 |
| 源码组成 | src/main.c:时钟、GPIO、USART 配置,fputc 重定向实现与打印调用;inc/main.h:实例、发送引脚与复用号宏;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | USARTx 为 USART3(Tx PA9/GPIO_AF17),复用推挽、上拉。波特率 115200、8 位字长、1 位停止位、无校验; 只用发送引脚,重定向函数每送一个字节前都等待发送完成标志。 |
| 程序与数据路径 | main 配置时钟、GPIO 与 USART3 后使能,随后调用 printf 输出一行提示。每打印一个字符都会进入 fputc,等 USART_FLAG_TXC 置位后把字符写入数据寄存器,返回后主循环空转。 |
| 主要 API | USART_Init、USART_Enable、USART_SendData、USART_GetFlagStatus |
| 验证方法 | 把 USART3_Tx(PA9)接 PC 串口或串口工具,波特率设为 115200,复位运行; 终端上出现 USART Printf Example: retarget the C library printf function to the USART 即表示打印成功。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开;重定向依赖 C 库钩子 fputc,若改用其它串口只需修改实例宏并相应配置引脚。工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例用 C 库的重定向钩子把标准输出接到串口,之后就能直接用 printf 打印。
数据路径: printf → C 库 → fputc → 等待 USART_FLAG_TXC → USART_SendData → USART3 → PC 终端
1. 把发送引脚配为复用推挽。 只需要一根发送线,配成复用推挽并上拉即可。
GPIO_InitType GPIO_InitStructure;
/* Initialize GPIO_InitStructure */
GPIO_InitStruct(&GPIO_InitStructure);
/* Configure USARTy Tx as alternate function push-pull */
GPIO_InitStructure.Pin = USARTx_TxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate = USARTx_Tx_GPIO_AF;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);
2. 初始化串口并用 printf 输出。 参数按 115200 波特率配置,使能之后直接调用 printf 输出提示字符串。
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.OverSampling = USART_16OVER;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx */
USART_Enable(USARTx, ENABLE);
/* Output a message on Hyperterminal using printf function */
printf("USART Printf Example: retarget the C library printf function to the USART\r\n");
3. 用 fputc 完成重定向。 C 库每输出一个字符都会调用一次 fputc,这里等发送完成后把字符写进数据寄存器。
int fputc(int ch, FILE* f)
{
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXC) == RESET)
{
}
USART_SendData(USARTx, (uint8_t)ch);
return (ch);
}
对应源码: src/main.c、inc/main.h
5.28.3.15 SmartCard 智能卡通信
工程目录: projects/n32h49x_EVAL/examples/USART/SmartCard/
复位智能卡并进入 T0 激活流程→发送取随机数命令并接收应答→执行 PPS 后重新握手→按状态字判决并打印随机数
| 项目 | 源码解读 |
|---|---|
| 功能 | SC_USART(USART3)工作在智能卡接口模式,经复位与 T0 协议激活后向智能卡发送取随机数命令,再按状态字判断命令是否正常完成并打印随机数。 |
| 源码组成 | src/main.c:系统初始化、智能卡测试流程与热复位、状态字判决与打印;src/smartcard.c:智能卡接口初始化、APDU 指挥、PPS 配置、字节收发与 DMA 配置;inc/smartcard.h:实例、引脚、DMA 与协议常量;src/delay.c、src/n32h49x_it.c:延时与中断服务;readme.txt:功能、环境、引脚连接与测试步骤。 |
| 关键配置 | SC_USART 为 USART3(I/O PB8/GPIO_AF17、CK PC12/GPIO_AF6),复位用 PB9,打印口为 USART1(PA9、115200)。时钟分频 40(智能卡工作时钟 2.5MHz)、保护时间 16、1.5 停止位、偶校验、9 位字长; DMA 用 DMA1_CH7 发送、DMA1_CH6 接收。 |
| 程序与数据路径 | main 先做系统初始化,再进入 Test_PSAM 配置时钟分频、保护时间与停止位,打开校验错误与帧错误中断后使能智能卡接口。T0 激活完成后发送 SC_GET_A2R 命令取随机数,按返回的状态字 SW1/SW2 分支打印结果,最后做一次热复位并反初始化。 |
| 主要 API | USART_Init、USART_SetPrescaler、USART_SetGuardTime、USART_ClockInit、USART_ConfigInt、USART_SetSmartCardNACK、USART_EnableSmartCard、USART_SendData |
| 验证方法 | 按 readme 把 USART3_Tx(PB8)接智能卡 I/O、USART3_CK(PC12)接 CLK、PB9 接 RST,并接好 3V3 与 GND; 复位运行,在 115200 的打印口查看智能卡命令状态字与随机数数据。 |
| 使用提示 | 需先接好智能卡的时钟、复位、电源与地; 智能卡波特率由时钟分频与保护时间共同决定,要先定好工作时钟再算波特率; NACK 传输与应用 PPS 必须按智能卡支持的命令逐条执行,重握手期间不要断电。 工程基于全功能板 N32H497ZGL7_EVB V1.0,开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例按 ISO7816 的 T0 协议与智能卡握手,读写都由字节级收发加状态机完成。
数据路径: SC_Init → 复位与 T0 激活 → APDU 命令(取随机数)→ 智能卡应答数据与状态字 → 判决打印 → 热复位与反初始化
1. 设置分频、保护时间与卡时钟。 分频决定智能卡工作时钟,保护时间决定两个字符之间的最小间隔,卡时钟单独初始化。
/* SC_USART Clock set to 3MHz (PCLK1 = 120 MHZ / 40) */
USART_SetPrescaler(SC_USART, SC_InitCfg->Clk_Div >> 1);
/* USART Guard Time set to 16 Bit */
USART_SetGuardTime(SC_USART, SC_InitCfg->GT);
USART_ClockInitStructure.Clock = USART_CLK_ENABLE;
USART_ClockInitStructure.Polarity = USART_CLKPOL_LOW;
USART_ClockInitStructure.Phase = USART_CLKPHA_1EDGE;
USART_ClockInitStructure.LastBit = USART_CLKLB_ENABLE;
USART_ClockInit(SC_USART, &USART_ClockInitStructure);
2. 初始化接口、打开错误中断并选择 NACK 行为。 9 位字长配偶校验,校验错误与帧错误各开一个中断,最后按配置决定是否发 NACK 并使能智能卡接口。
USART_Init(SC_USART, &USART_InitStructure);
/* Enable the SC_USART Parity Error Interrupt */
USART_ConfigInt(SC_USART, USART_INT_PEF,ENABLE);
/* Enable the SC_USART Framing Error Interrupt */
USART_ConfigInt(SC_USART, USART_INT_ERRF,ENABLE);
/* Enable SC_USART */
USART_Enable(SC_USART,ENABLE);
/* Enable the NACK Transmission */
if(SC_InitCfg->NackEn == 0)
{
USART_SetSmartCardNACK(SC_USART,DISABLE);
}
else if(SC_InitCfg->NackEn == 1)
{
USART_SetSmartCardNACK(SC_USART,ENABLE);
}
else
{
log_info("\r\n NACK Enable value is error !!! \r\n");
}
/* Enable the Smartcard Interface */
USART_EnableSmartCard(SC_USART,ENABLE);
3. 测试流程:激活、取随机数并按状态字判决。 配置参数后循环驱动状态机直到卡片激活,再发取随机数命令并按 SW1/SW2 判断结果。
log_info("USARTx Smart_Card Test Start\r\n");
SC_InitCfg.Clk_Div = 40; //SC_USART Clock set to (PCLK1 = SC_USART MHZ / Clk_Div) MHz
SC_InitCfg.GT = 16;
SC_InitCfg.StopBits = 3;
SC_InitCfg.Parity = 1;
SC_InitCfg.NackEn = 0; // 0 - Disable NACK, 1 - Enable NACK
SCState = SC_POWER_ON;
SC_APDU_Init(&SC_ADPU, 0x00, SC_GET_A2R, 0x00, 0x00, 0x00, NULL, 0);
while(SCState != SC_ACTIVE_ON_T0)
{
SC_Handler(&SCState, &SC_ADPU, &SC_Responce, &SC_InitCfg);
}
/* Apply the Procedure Type Selection (PPS) */
SC_PPSConfig();
SC_APDU_Init(&SC_ADPU, 0x00, 0x84, 0x00, 0x00, 0x00, NULL, 8);
SC_Handler(&SCState, &SC_ADPU, &SC_Responce, &SC_InitCfg);
for(i = 0; i < SC_ADPU.Body.LE; i++)
{
log_info("\r\n SC_Responce.Data[%d] = 0x%02x \r\n", i, SC_Responce.Data[i]);
}
printf("\r\n SC_Responce.SW1 = 0x%02x \r\n", SC_Responce.SW1);
printf("\r\n SC_Responce.SW2 = 0x%02x \r\n", SC_Responce.SW2);
if((SC_Responce.SW1 == 0x90) && (SC_Responce.SW2 == 0x00))
{
对应源码: src/main.c、src/smartcard.c、inc/smartcard.h
5.28.3.16 Synchronous 同步模式收发
工程目录: projects/n32h49x_EVAL/examples/USART/Synchronous/
USART1 配成同步模式、SPI1 配成从模式→USART1 发送、SPI1 接收→反向由 SPI1 发送、USART1 接收→比较两组收发数据
| 项目 | 源码解读 |
|---|---|
| 功能 | USARTy(USART1)工作在同步模式并输出 CK,与从模式的 SPIy(SPI1)三线互联,双向收发后比对两组数据。 |
| 源码组成 | src/main.c:时钟、GPIO、同步时钟、USART 与 SPI 配置、双向收发与数据比对;inc/main.h:USART 与 SPI 实例、数据引脚、CK 与复用号宏;readme.txt:功能、环境、三线连接与测试步骤。 |
| 关键配置 | USARTy 为 USART1(Tx PA9、Rx PA10、CK PA8,复用 GPIO_AF5),SPIy 为 SPI1(SCK PA5、MISO PA6、MOSI PA7,复用 GPIO_AF1)。USART 波特率 115200、8 位字长、1 位停止位、无校验,CK 极性低、第二边沿采样、最后一位输出脉冲; SPI 为从模式、8 位、CPOL 低、CPHA 第二边沿、软件 NSS、LSB 优先。 |
| 程序与数据路径 | main 配置时钟、GPIO、同步时钟、USART 与 SPI 后使能,先由 USART1 发、SPI1 收存入 RxBuffer2。再由 SPI1 发、USART1 收存入 RxBuffer1,期间分别用发送完成与接收非空标志同步,最后用 Buffercmp 比较两组缓冲区。 |
| 主要 API | USART_Init、USART_ClockInit、USART_Enable、USART_SendData、USART_ReceiveData、USART_GetFlagStatus、SPI_I2S_ReceiveData |
| 验证方法 | 把 USART1_Tx(PA9)接 SPI1_MOSI(PA7)、USART1_Rx(PA10)接 SPI1_MISO(PA6)、USART1_Clk(PA8)接 SPI1_SCK(PA5); 拔掉串口打印跳帽后复位运行,依次查看 TransferStatus1 与 TransferStatus2,均为 PASSED 表示收发一致。 |
| 使用提示 | 需先把开发板 NS-LINK 的 MCU_TX、MCU_RX 跳线帽断开,并拔除串口打印跳帽;USART 同步模式由 CK 提供时钟,对端必须配成从模式并让时钟极性与相位与之匹配; USART 作为提供时钟的一方,反向接收时要靠发送哑元字节产生时钟才能读回数据。 工程基于 N32H497ZGL7_STB V1.0,开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
USART 同步模式用 CK 输出时钟,与从模式 SPI 组成三线总线,两端靠标志逐字节对齐。
数据路径: TxBuffer1 → USART1(同步)→ SPI1 → RxBuffer2;TxBuffer2 → SPI1 → USART1 → RxBuffer1 → Buffercmp 比较
1. 打开同步时钟并设好极性、相位。 时钟只在发送时输出,采样相位与最后一位脉冲都要与对端 SPI 对应。
USART_ClockInitStructure.Clock = USART_CLK_ENABLE;
USART_ClockInitStructure.Polarity = USART_CLKPOL_LOW;
USART_ClockInitStructure.Phase = USART_CLKPHA_2EDGE;
USART_ClockInitStructure.LastBit = USART_CLKLB_ENABLE;
USART_ClockInit(USARTy, &USART_ClockInitStructure);
2. 配置 USART 参数并使能。 参数按 115200 波特率配置,配置完成后使能 USART1。
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.OverSampling = USART_16OVER;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTy */
USART_Init(USARTy, &USART_InitStructure);
/* Enable the USARTy */
USART_Enable(USARTy, ENABLE);
3. USART1 发、SPI1 收。 每发一字节等发送完成,再等 SPI 接收非空并读出数据。
while(NbrOfDataToRead2--)
{
/* Write one byte in the USARTy Transmit Data Register */
USART_SendData(USARTy, TxBuffer1[TxCounter1++]);
/* Wait until end of transmit */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXC) == RESET)
{
}
/* Wait the byte is entirely received by SPIy */
while (SPI_I2S_GetStatus(SPIy, SPI_I2S_RNE_FLAG) == RESET)
{
}
/* Store the received byte in the RxBuffer2 */
RxBuffer2[RxCounter2++] = SPI_I2S_ReceiveData(SPIy);
}
4. SPI1 发、USART1 收。 USART 是提供时钟的一方,接收时要发一个哑元字节产生时钟,再等接收非空读回数据。
while (NbrOfDataToRead1--)
{
/* Wait until end of transmit */
while (SPI_I2S_GetStatus(SPIy, SPI_I2S_TE_FLAG) == RESET)
{
}
/* Write one byte in the SPIy Transmit Data Register */
SPI_I2S_TransmitData(SPIy, TxBuffer2[TxCounter2++]);
/* Send a Dummy byte to generate clock to slave */
USART_SendData(USARTy, DYMMY_BYTE);
/* Wait until end of transmit */
while (USART_GetFlagStatus(USARTy, USART_FLAG_TXC) == RESET)
{
}
/* Wait the byte is entirely received by USARTy */
while (USART_GetFlagStatus(USARTy, USART_FLAG_RXDNE) == RESET)
{
/* Overflow data loss */
if(USART_GetFlagStatus(USARTy, USART_FLAG_OREF) != RESET)
{
USARTy->DAT;
}
}
/* Store the received byte in the RxBuffer1 */
RxBuffer1[RxCounter1++] = USART_ReceiveData(USARTy);
}
对应源码: src/main.c、inc/main.h
5.28.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 通信模式互斥 | 启用某一模式前须将互斥位清零:同步模式须清 LINMEN、SCMEN、HDMEN、IRDAMEN;单线半双工须清 CLKEN、LINMEN、SCMEN、IRDAMEN;IrDA 须清 CLKEN、STPB[1:0]、LINMEN、HDMEN、SCMEN;LIN 须清 STPB[1:0]、CLKEN、SCMEN、HDMEN、IRDAMEN;智能卡须清 LINMEN、HDMEN、IRDAMEN。 |
用户手册 |
| 使能后不可写的控制位 | USART_CTRL1 的 TEDEN、IFCEN、SWAP、OSPM、DEAT、DEDT、DEP、DEM 只能在禁止 USART(UEN=0)时写入;这些配置须在使能 USART 前完成。 |
用户手册 |
| 过采样位在特定模式下的取值 | 在 LIN、IrDA 与智能卡模式下 USART_CTRL1.OSPM 必须保持为 0。 |
用户手册 |
| 波特率寄存器写条件 | USART_CTRL1.UEN=1 时不能写 USART_BRCF;通信过程中不要改变波特率寄存器数值,写入新值后波特率计数器立即替换。 |
用户手册 |
| 传输中修改字长 | 数据传输(发送或接收)过程中不能修改 USART_CTRL1.WL。 |
用户手册 |
| 传输中关闭收发器 | 数据传输时清零 USART_CTRL1.TXEN 会使波特率计数器停止,破坏正在发送的数据;接收过程中清零 USART_CTRL1.RXEN 会丢失当前接收数据。 |
用户手册 |
| 同步时钟配置时机 | 同步模式的 CLKPOL、CLKPHA、LBCLK 只能在发送器与接收器都被禁用时配置;未发送数据时无法接收同步数据。 |
用户手册 |
| 接收超时重新计数 | 接收超时后须清除 USART_STS.RTOF(写 USART_CTRL2.RTOCF),否则不会重新开始超时计数;清除后直到接收到下一个数据才开始计数。 |
用户手册 |
| 数据错误丢弃与 FIFO 配置 | 数据错误丢弃(PEFLOSE/FEFLOSE/NEFLOSE)只在 FIFO 模式下的接收数据有效;使能 FIFO 时阈值 TXFTCFG/RXFTCFG 不要配置为 2'b00;USART_FIFO.CLR 为脉冲位,写 1 后由硬件自动归零。 |
用户手册 |
| 部分实例不支持的模式 | UART5、UART6、UART7、UART8 不支持同步模式与智能卡模式;CLKEN、CLKPHA、CLKPOL、LBCLK 对其无效,SCMEN、SCNACK 对这些实例强制为 0。 |
用户手册 |
| 驱动器使能时间 | 使能 USART_CTRL1.DEM 后 DEAT 不能配置为 0(最小为 1);DEAT、DEDT 需在 UEN=0 时写入。 |
用户手册 |
| CTS 无效时写入数据 | nCTS 无效(高电平)时写入数据寄存器的数据会保持,直到 nCTS 有效后才开始发送; 若传输中 nCTS 被拉高,则在当前数据传输完成后停止发送。 |
用户手册 |