在之前的博客中分析了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 */
上一篇:stm32专题十一:USART(二)结构框图
下一篇:stm32专题十一:USART(四)USART编程
推荐阅读
史海拾趣
随着客户需求的多样化,Cal Test Electronics开始关注小批量定制型测试电缆组件的市场。公司利用自身的技术优势和生产能力,为客户提供个性化的定制服务。这些定制产品不仅满足了客户的特殊需求,也提高了公司的市场竞争力。通过这一策略,Cal Test Electronics成功打开了一个全新的市场领域,为公司的发展注入了新的动力。
在全球化的大背景下,企业之间的合作与共赢成为了一种趋势。动运科技积极寻求与全球知名企业的战略合作,共同推动电子行业的发展。例如,公司与香港希荻微的合作就是一个典型的例子。通过独占许可的方式,希荻微获得了动运科技在中国大陆及港澳台地区生产、销售与自动对焦及光学防抖技术相关的产品的权利,并有权使用授权技术进行技术改进及新产品研发。这一合作不仅为双方带来了互利共赢的机会,也为整个电子行业的发展注入了新的活力。
随着全球经济的不断发展,亚洲市场逐渐成为通信行业的重要增长点。康普公司敏锐地捕捉到了这一机遇,于1997年在苏州工业园区成立了康普通讯技术(中国)有限公司,这是康普在亚洲开设的第一家工厂。该工厂的成立不仅提高了康普在亚洲市场的生产效率,也为其进一步开拓亚洲市场提供了有力的支持。此后,康普在亚洲市场的业务逐渐扩大,为众多国内大型项目提供了网络解决方案。
在通信行业,技术的不断创新和产品的持续升级是企业保持竞争力的关键。康普公司一直注重研发和创新,不断推出具有竞争力的新产品和解决方案。例如,在2004年,康普成立了CCS(连接解决方案)工厂,主要生产宽带同轴电缆、网络对绞线缆以及铜和光纤连接器系列产品。这些产品不仅满足了市场对于高速、高质量网络连接的需求,也进一步巩固了康普在通信行业的领先地位。
随着数字化和智能化技术的不断发展,迪一电子公司意识到必须跟上时代的步伐。于是,公司开始推进数字化转型和智能化生产。通过引入先进的生产设备和信息系统,优化生产流程,提高生产效率。同时,公司还注重人才培养和引进,建立了一支高素质的技术和管理团队。这些努力使迪一电子在数字化和智能化方面取得了显著成果,提高了公司的竞争力和市场地位。
随着物联网技术的快速发展,安信可也迎来了技术升级的关键时刻。2014年9月,安信可成功引入ESP8266 SoC方案,这一技术升级为公司带来了更多的市场机会。到了2016年5月,安信可更是成功转型为一站式物联网模组解决方案提供商,为客户提供从模组到应用的全方位服务。
本人计算机专业本科,去年毕业,现在在一家生产(确切的定义应该是“研发”,因为地质仪器需求量比较少,我们更多的精力投放在手头的科研项目上)地质勘探仪器的公司工作,公司的总工曾是文革后中科院电子所第一届研究生,我就在他的手下学习。大学 ...… 查看全部问答∨ |
|
把主机拆开除灰尘,想想顺便也把电源也除除灰,拆开一看,感觉哪个PFC有点不对,顺便拆开看看,由于这台电脑是第一次配的,是一款杂牌电源,当时那JS说230块机箱电源随便选,觉得有问题,不过当时没经验,也就没管那么多~ 凡来坛里的一看就知道, ...… 查看全部问答∨ |
我在“控制面板\\添加硬件"中按照向导安装到最后,点击完成的哪个界面 出现如下提示信息: 安装设备时出现了一个错误 名称已用作服务或服务显示名 各位大哥指点一下,可能是那里错误!说出解决的方法,越详细越好,哈哈 先谢谢各位捧场的大 ...… 查看全部问答∨ |
代码如下: always @(negedge clk or negedge rst_n) begin if(!rst_n) begin address <= 1 ...… 查看全部问答∨ |
Beaglebone学习之5-外围电路设计完成(含原理图和PCB) 最近公司事情太忙,迟到这么久的设计终于完成了,不然真的辜负EEWORLD和大家的信任了(板子和奖金都到手了),今天已经把板子发出去做,周末应该就能回来了,到时再分享硬件调试和软件开发细节 另外板子做了10块,有兴趣的我可以赠送几块出来,还有 ...… 查看全部问答∨ |
怎样在IAR中建立一个project含有多个file? 不同file之间的变量信息通过什么传输?全局变量为什么不行? (像下图一样,一个工程中包含多个文件)… 查看全部问答∨ |
最近工作各种忙啊,不过还好终于今天抽点时间来写点东西咯,好了不说废话了,上篇主要介绍了硬件部分的设计,今天就说说程序设计吧。 MF RC522 利用了先进的调制 ...… 查看全部问答∨ |