历史上的今天
今天是:2024年10月21日(星期一)
2021年10月21日 | stm32专题十一:USART(三)初始化结构体和标准库函数分析
2021-10-21 来源:eefocus
在之前的博客中分析了stm32串口的结构,和详细的发送、接受过程。现在来分析固件库中对于USART的标准函数
typedef struct
{
uint32_t USART_BaudRate; // 波特率
uint16_t USART_WordLength; // 帧数据长度(8位还是9位)
uint16_t USART_StopBits; // 停止位
uint16_t USART_Parity; // 校验
uint16_t USART_Mode; // 模式:单收、单发或收发
uint16_t USART_HardwareFlowControl; // 硬件流控
} USART_InitTypeDef;
固件库中初始化函数,就是往前一篇博客中提到的控制寄存器USART_CR1 USART_CR2中写入相应的数据,并计算波特率的值,然后写入BRR寄存器。
/**
* @brief Initializes the USARTx peripheral according to the specified
* parameters in the USART_InitStruct .
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_InitStruct: pointer to a USART_InitTypeDef structure
* that contains the configuration information for the specified USART
* peripheral.
* @retval None
*/
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
{
uint32_t tmpreg = 0x00, apbclock = 0x00;
uint32_t integerdivider = 0x00;
uint32_t fractionaldivider = 0x00;
uint32_t usartxbase = 0;
RCC_ClocksTypeDef RCC_ClocksStatus;
/* The hardware flow control is available only for USART1, USART2 and USART3 */
// 硬件流控只有在USART中才能使用,UART中不能用
if (USART_InitStruct->USART_HardwareFlowControl != USART_HardwareFlowControl_None)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
usartxbase = (uint32_t)USARTx;
/*---------------------------- USART CR2 Configuration -----------------------*/
// 先保存USART_CR2寄存器的状态
tmpreg = USARTx->CR2;
/* Clear STOP[13:12] bits */
// 清除CR2的停止位,其他位保持不变
tmpreg &= CR2_STOP_CLEAR_Mask;
/* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/
/* Set STOP[13:12] bits according to USART_StopBits value */
// 根据配置的停止位,写入到相应的位置
tmpreg |= (uint32_t)USART_InitStruct->USART_StopBits;
/* Write to USART CR2 */
// 八停止位配置写进CR2寄存器
USARTx->CR2 = (uint16_t)tmpreg;
/*---------------------------- USART CR1 Configuration -----------------------*/
tmpreg = USARTx->CR1;
/* Clear M, PCE, PS, TE and RE bits */
// 清除字长、校验、校验使能、发送和接收使能的位,再根据配置写入
tmpreg &= CR1_CLEAR_Mask;
/* Configure the USART Word Length, Parity and mode ----------------------- */
/* Set the M bits according to USART_WordLength value */
/* Set PCE and PS bits according to USART_Parity value */
/* Set TE and RE bits according to USART_Mode value */
tmpreg |= (uint32_t)USART_InitStruct->USART_WordLength | USART_InitStruct->USART_Parity |
USART_InitStruct->USART_Mode;
/* Write to USART CR1 */
// 把配置的字长、校验、模式写入到CR1寄存器
USARTx->CR1 = (uint16_t)tmpreg;
/*---------------------------- USART CR3 Configuration -----------------------*/
tmpreg = USARTx->CR3;
/* Clear CTSE and RTSE bits */
// 清除串口的发送、接收硬件流控
tmpreg &= CR3_CLEAR_Mask;
/* Configure the USART HFC -------------------------------------------------*/
/* Set CTSE and RTSE bits according to USART_HardwareFlowControl value */
tmpreg |= USART_InitStruct->USART_HardwareFlowControl;
/* Write to USART CR3 */
// 把配置的硬件流控制写入到CR3寄存器(通常不适用硬件流控)
USARTx->CR3 = (uint16_t)tmpreg;
/*---------------------------- USART BRR Configuration -----------------------*/
/* Configure the USART Baud Rate -------------------------------------------*/
RCC_GetClocksFreq(&RCC_ClocksStatus);
if (usartxbase == USART1_BASE)
{
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
}
else
{
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
}
/* Determine the integer part */
if ((USARTx->CR1 & CR1_OVER8_Set) != 0)
{
/* Integer part computing in case Oversampling mode is 8 Samples */
integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate)));
}
else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
{
/* Integer part computing in case Oversampling mode is 16 Samples */
integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));
}
tmpreg = (integerdivider / 100) << 4;
/* Determine the fractional part */
fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
/* Implement the fractional part in the register */
if ((USARTx->CR1 & CR1_OVER8_Set) != 0)
{
tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
}
else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
{
tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
}
/* Write to USART BRR */
USARTx->BRR = (uint16_t)tmpreg;
}
接下来是在同步串口通信中使用的结构体,虽然这个用的很少,但学习时还是应该全面,因此也分析一下
typedef struct
{
uint16_t USART_Clock; // 时钟使能
uint16_t USART_CPOL; // 时钟极性(High或者Low)
// 表示串口空闲时时钟是高电平还是低电平
uint16_t USART_CPHA; // 时钟相位(USART_CPHA_1Edge或者USART_CPHA_2Edge)
// 表示在时钟的第一个边沿采集数据还是第二个边沿采集数据
// 时钟的极性和相位一定是配合使用的
uint16_t USART_LastBit; // 选择最后一位数据的时钟会不会发出
} USART_ClockInitTypeDef;
我们再看以一下固件库中的其他常用的配置函数
// 使能串口,配置的是CR1_UE位
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected USART by setting the UE bit in the CR1 register */
USARTx->CR1 |= CR1_UE_Set;
}
else
{
/* Disable the selected USART by clearing the UE bit in the CR1 register */
USARTx->CR1 &= CR1_UE_Reset;
}
}
// DMA请求
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DMAREQ(USART_DMAReq));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the DMA transfer for selected requests by setting the DMAT and/or
DMAR bits in the USART CR3 register */
USARTx->CR3 |= USART_DMAReq;
}
else
{
/* Disable the DMA transfer for selected requests by clearing the DMAT and/or
DMAR bits in the USART CR3 register */
USARTx->CR3 &= (uint16_t)~USART_DMAReq;
}
}
然后是中断配置函数,有很多个中断可以选择。这个函数写的还是有点复杂,仔细看,起始可以发现,基本就是如下过程。通过中断标志,来判断该中断由CR1(偏移地址0X0C)还是CR2(偏移0X10),或者是CR3(偏移0X14)。然后把相应寄存器的中断使能标志位置1。
/**
* @brief Enables or disables the specified USART interrupts.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_IT: specifies the USART interrupt sources to be enabled or disabled.
* This parameter can be one of the following values:
* @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5)
* @arg USART_IT_LBD: LIN Break detection interrupt
* @arg USART_IT_TXE: Transmit Data Register empty interrupt
* @arg USART_IT_TC: Transmission complete interrupt
* @arg USART_IT_RXNE: Receive Data register not empty interrupt
* @arg USART_IT_IDLE: Idle line detection interrupt
* @arg USART_IT_PE: Parity Error interrupt
* @arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
* @param NewState: new state of the specified USARTx interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
{
uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;
uint32_t usartxbase = 0x00;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CONFIG_IT(USART_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
/* The CTS interrupt is not available for UART4 and UART5 */
if (USART_IT == USART_IT_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
usartxbase = (uint32_t)USARTx;
/* Get the USART register index */
usartreg = (((uint8_t)USART_IT) >> 0x05);
/* Get the interrupt position */
itpos = USART_IT & IT_Mask;
itmask = (((uint32_t)0x01) << itpos);
if (usartreg == 0x01) /* The IT is in CR1 register */
{
usartxbase += 0x0C;
}
else if (usartreg == 0x02) /* The IT is in CR2 register */
史海拾趣
|
我使用的smdk2410的lcd驱动中有这样的代码 //TFT timing parameter for V16C6448AB(PRIME VIEW) #define VBPD ((1-1)&0xff) #define VFPD ...… 查看全部问答> |
|
工控工程师群70677754——交流开发经验,解决工程难题,寻找合作机会,非专业人士勿入。 工控设计群——70677754,非高手莫进,加入请写明水平及方向。 本群以交流开发经验,解决工程难题,寻找合作机会为目标。 欢迎热爱工控事业的工程师们入群 51,ARM,DSP Keil c,Proteus. Linux.RTOS.网络 机器视觉 运动控制… 查看全部问答> |
|
eboot.bin文件烧进系统以后,会自行压缩成eboot.nb0文件。我现在需要知道这个压缩的过程的代码是在哪个文件的哪个函数里的!有知道的吗??? 我找了F:\\WINCE500\\PUBLIC\\COMMON\\OAK\\DRIVERS\\ETHDBG\\BLCOMMON的BLCOMMON.c文件的DownloadImage函 ...… 查看全部问答> |
|
;...以下这段代码写OptionBytes,并造成STVD和STVP均无法操作该器件(锁死) ld a,#$56 ld $5062,a ld a,#$ae ld $5062,a;Unlock Program Memory ld a,#$ae ld $5064,a ld a,#$56 ld $5064,a;Unlock DataEEPROM and Optionbytes ld&nbs ...… 查看全部问答> |
|
我做的是超声波避障小车,用的单片机是“飞思卡尔”的HCS12,现在想要实现的是在小车前端的两侧各安装一组超声波测距模块(HC-SR04),利用单片机控制两组超声波模块发射超声波,然后比较接收到的超声波信号,哪边信号强(比较计数器时间)证明哪边 ...… 查看全部问答> |
|
有没有谁帮忙把BRD的文件导出成Altium Designer Winter 09可以打开的文件,谢谢了。 请留下您的邮箱,我发您邮箱,或者哪位大侠能帮我导出好了,发我邮箱; zhangyibing1986090@163.com 谢谢各位了! … 查看全部问答> |




