起初
stm32 v3.5 库函数里面,对于串口USART有这样两个函数:
USART_ClearFlag()和USART_ClearITPendingBit()
查库函数定义,说一个是清除标志,一个是清除中断预处理位。然后我看了stm32f10x_usart.c文件,发现两个函数都操作的是USART->SR寄存器,但是这个寄存器只有一组标志位,没有什么中断预处理位。。
实际上两个函数实现的功能是一样的,都是清除相对应的标志位,只是标志位和中断位含义不一样,是标志位但
是不一定会产生中断。例如:
#define USART_IT_TXE ((uint16_t)0x0727)
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_IT_RXNE ((uint16_t)0x0525)
这是中断位,可以产生中断
#define USART_FLAG_TXE ((uint16_t)0x0080)
#define USART_FLAG_TC ((uint16_t)0x0040)
#define USART_FLAG_RXNE ((uint16_t)0x0020)
这是标志位,有的标志位不能产生中断
标志位在程序中可以作为判定条件,支持程序的运行,中断则是跳转到中断函数执行。两个函数实现的功能是一
样的,在中断程序中可以用两个中的任一个。我想区分两个函数是为了更清晰吧。
还有
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_FLAG_TC ((uint16_t)0x0040)
这两个数值不同是因为标志位只是为了清除标志位而设的,而中断位设置成这个值是因为在其他函数中这一位还
有其他用途。而且还要注意:
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
assert_param(IS_USART_PERIPH_FLAG(USARTx, USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */
USARTx->SR = (uint16_t)~USART_FLAG;
}
这一步 USARTx->SR = (uint16_t)~USART_FLAG; 似乎应该是 USARTx->SR &= (uint16_t)~USART_FLAG;
其实状态位只能有硬件置位,软件只能读和清零,所以这样写也是正确的。
没有很明白,所以转在这里,等我哪天灵光乍现了,再来加上我的理解
上面的内容是别人的,我略作修改,下面的内容是我原创。不知道本文到底是属于原创还是转载,但是......我的更简洁、精辟
-----------------------------------------------------------------------------------------------------------------------
灵光乍现了
我是在使用TC的时候遇见这个问题的,所以这里就只分析TC这个位
先研究简单点的USART_ClearFlag函数
//调用形式
USART_ClearFlag(USART3,USART_FLAG_TC);
//USART_FLAG_TC的定义
#define USART_FLAG_TC ((uint16_t)0x0040)
//USART_ClearFlag函数的原型
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
assert_param(IS_USART_PERIPH_FLAG(USARTx, USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */
USARTx->SR = (uint16_t)~USART_FLAG;
}
一目了然,最后USARTx->SR = ~(0100'0000);
再来研究复杂点的USART_ClearITPendingBit函数(注意,这两个函数的第二个参数,是不一样的)
//调用形式
USART_ClearITPendingBit(USART3,USART_IT_TC);
//USART_IT_TC的定义
#define USART_IT_TC ((uint16_t)0x0626)//=0000'0110'0010'0110
//USART_ClearITPendingBit的函数原型
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)
{
uint16_t bitpos = 0x00, itmask = 0x00;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_IT(USART_IT));
assert_param(IS_USART_PERIPH_IT(USARTx, USART_IT)); /* The CTS interrupt is not available for UART4 and UART5 */
bitpos = USART_IT >> 0x08; //=0000'0110
itmask = (uint16_t)((uint16_t)0x01 << bitpos); //=0100'0000
USARTx->SR = (uint16_t)~itmask; //=~(0100'0000)
}
可以看到最后还是USARTx->SR=~(0100'0000);
对比一下USART_ClearFlag和USART_ClearITPendingBit的参数
USART_ClearFlag的参数 USART_ClearITPendingBit的参数
USART_FLAG_CTS = 0x0200 USART_IT_CTS = 0x096A
USART_FLAG_LBD = 0x0100 USART_IT_LBD = 0x0846
USART_FLAG_TC = 0x0040 USART_IT_TC = 0x0626
USART_FLAG_RXNE = 0x0020 USART_IT_RXNE = 0x0525
这里可以发现一个规律USART_ClearFlag参数只有一个位是“1”,其位置正好等于USART_ClearITPendingBit的参数左移八位后的结果,所以这里可以非常非常肯定的讲:函数USART_ClearFlag和函数USART_ClearITPendingBit的功能totally一样
----------------------------------------------------------------------------------------------------------------------------
涉及内容扩展:
STM32的USART发送数据时如何使用TXE和TC标志
在USART的发送端有2个寄存器,一个是程序可以看到的寄存器——发送数据寄存器(通过USART_DR查看),另一个是程序看不到的寄存器——发送移位寄存器,对应的有两个USART数据发送标志,一个是TXE=发送数据寄存器空,另一个是TC=发送移位寄存器空。
(这粗箭头和这细箭头,简直不要太形象哦,粗箭头是八位八位的传,细箭头是一位一位的传)
当USART_DR中的数据传送到移位寄存器后,TXE被设置,此时移位寄存器开始向TX信号线按位传输数据,但因为TDR已经变空,所以程序可以把下一个要发送的字节(操作USART_DR)写入TDR中,而不必等到移位寄存器中所有位发送结束,所有位发送结束时(送出停止位后)硬件会设置TC标志。
另一方面,在刚刚初始化好USART还没有发送任何数据时,也会有TXE标志,因为这时发送数据寄存器是空的。TXEIE和TCIE的意义很简单,TXEIE允许在TXE标志为'1'时产生中断,而TCIE允许在TC标志为'1'时产生中断。
至于什么时候使用哪个标志,需要根据你的需要自己决定。但我认为TXE允许程序有更充裕的时间填写TDR寄存器,保证发送的数据流不间断。TC可以让程序知道发送结束的确切时间,有利于程序控制外部数据流的时序。
三种发送方法
1、不开发送完成中断:
/*******************************************************************************
* 函数名 : UART1_SendString
* 描述 : USART1发送字符串
* 输入 : *s字符串指针
* 注释 :0==RESET,表示发送还未完成
USART_FLAG_TC!=RESET,就是=SET,表示发送完成,此时执行USART_GetFlagStatus会把USART_FLAG_TC清零(未证实)
*******************************************************************************/
void UART1_SendString(u8* s)
{
while(*s)//检测字符串结束符
{
//USART_FLAG_TC==RESET时,表示发送还未完成。
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1 ,*s++);//发送当前字符
}
}
2、开中断,额外设置一个标志:
u8 FLAG_TC=0;//定义全局变量
/*******************************************************************************
* 函数名 : UART1_SendString
* 描述 : USART1发送字符串
* 输入 : *s字符串指针
*******************************************************************************/
void UART1_SendString(char* s)
{
FLAG_TC=0;//提前准备一下
while(*s)//检测字符串结束符
{
USART_SendData(USART1 ,*s++);//发送当前字符
while( FLAG_TC==0); //0:发送还未完成;1:发送完成
FLAG_TC=0;
}
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)//发送完成中断,= SET
{
USART_ClearITPendingBit(USART1,USART_IT_TC);
FLAG_TC=1;
}
}
开中断时,就不能通过简单的判断标志位USART_FLAG_TC的状态去决定能否发送下一个字符。比方说,使用
while(*s)
{
USART_SendData(USART1 ,*s++);//发送字符
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
...
}
执行完发送字符的语句后,因为不可能这么快完成发送,所以程序接下来执行的是while语句。在等待期间,字符发送完毕,这时就会进入到中断,如果在中断里清除标志位,退出中断后,标志位USART_FLAG_TC仍然是RESET;如果不在中断里清除标志位,就不能退出中断。所以程序就会死在while里。
所以这里就需要额外设置一个标志。
3、开中断,数据发送由函数启动,在中断里完成:
//定义全局变量。也可以为了简化,把这四个参数结合起来包含在一个结构体里
u8 TxLength; //发送数据长度
u8 TxIndicator;//发送指示器,表示目前发送完成哪一位了,下面要发送的是第(TxIndicator+1)位
u8 TxBuff[256];//Data
u8 TxFnd; //发送完成标志
/*************************************************************************
*程序名称 : SendFirstByte
*功能 : 启动发送第一个字节
*@Notes : 鸡贼啊,剩下的都放在USART_FLAG_TC中断里面,因为这个中断是
发送完成中断,是利用“发送第一个字节”来“启动发送”
*@Notes : 需要注意,如果发送结果是乱码的话,一种供参考的解决方案是
把数据直接赋值给TxBuff,而不要通过函数的形参传递
*输入参数 : u8 txbuf[]: 需要发送的数据,u8 len : 数据中的字节数
*返回值 : 无
*************************************************************************/
void SendFirstByte( u8 txbuf[], u8 len )
{
TxBuff = txbuf;//需要发送的数据
TxLength = len ;//发送数据长度
TxIndicator = 1 ;//0已经发送,也是用来启动发送的
USART_SendData(USART1, txbuf[0]); /**@Notes:只发送了txbuf的第一个字节*/
}
/*************************************************************************
*程序名称 : USART1_IRQHandler
*功能 : 完成发送数据
*************************************************************************/
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{
USART_ClearITPendingBit(USART1,USART_IT_TC);
if( TxIndicator < TxLength )//数组的索引max永远小于数组元素的个数
{
USART_SendData(USART1, TxBuff[TxIndicator++]);
}
else//最后一字节数据发送完成
{
TxFnd = 0;
TxIndicator = 0;
}
}
}
USART收发过程中常遇问题总结:
Q:为什么使用USART发送一串字符,最后自接收到了最后一个?
A:是因为发送的间隔太短了,可以在发送每个字符之前先判断一下上一个字符是否发送完成,可以参考上面的“三种发送方法”
Q:为什么使用USART发送一串字符,有时候接收不到第一个字符,有时候又可以接收得到?
A:解决方案是把判断能否发送的语句放在发送数据之前
上一篇:stm32串口的flag和it标志位
下一篇:STM32F1x系列——外部中断
推荐阅读
史海拾趣
由于Crydom公司的发展涉及多个方面,且具体故事可能涉及公司内部信息或未公开资料,我无法直接提供5个精确到字数的电子行业里Crydom公司发展起来的相关故事。但我可以尝试根据已知信息,概括性地描述Crydom公司在电子行业中的一些重要发展事实。
- 固态继电器的发明与领导地位的确立
Crydom公司作为固态继电器的发明者,从一开始就奠定了在电子行业中的技术领先地位。固态继电器作为一种新型的电子开关,具有响应速度快、寿命长、可靠性高等优点,迅速在市场中获得了认可。Crydom凭借其在固态继电器技术领域的深厚积累,不断推出创新产品,满足了市场对高效、稳定电子开关的需求,逐渐确立了在行业中的领导地位。
- 质量保障体系的建立与完善
为了确保产品质量和客户满意度,Crydom建立了严格的质量保障体系。公司始终坚持“产品封装前后两次”“100%全检”的过程,对产品的每一个细节都进行严格把控。这种对质量的极致追求,使得Crydom的固态继电器在市场上获得了良好的声誉,赢得了众多客户的信赖。
- 定制化解决方案的提供
随着电子行业的不断发展,客户对产品的需求也日益多样化。Crydom公司敏锐地捕捉到这一市场变化,除了提供成千上万的即用型产品外,还能根据客户的具体应用需求,定制专属的固态继电器解决方案。这种灵活的服务模式,使得Crydom能够更好地满足客户的需求,进一步巩固了其在市场中的地位。
- 多元化市场的拓展
Crydom的固态继电器不仅在传统的工业领域得到了广泛应用,还逐渐拓展到了医疗、交通、军事以及航天等多元化市场。这些市场的开拓,不仅为Crydom带来了更多的商机,也进一步提升了其在电子行业中的影响力。
- 国际认证与合作的加强
Crydom公司一直致力于提升产品的国际竞争力。多年来,公司获得了多项国际认证,如ISO、UL、CE等,这些认证不仅证明了公司产品的高品质,也为其在国际市场上的拓展提供了有力支持。同时,Crydom还积极与全球知名的航空公司、电子企业等建立合作关系,通过技术交流和合作研发,不断提升自身的技术水平和市场竞争力。
这些发展事实只是Crydom公司在电子行业中发展的一部分缩影。如需更详细的故事或更深入的了解,建议查阅相关的行业报告、公司年报或专访文章。
在追求经济效益的同时,Caddock公司也注重环保和可持续发展。公司积极推行绿色制造理念,通过优化生产工艺、降低能耗和减少废弃物排放等措施,实现了环保与经济效益的双赢。此外,公司还致力于研发环保型电阻材料和技术,为推动电子行业的绿色发展做出了积极贡献。
这些故事展示了Caddock公司在电子行业发展的不同阶段所取得的成就和面临的挑战。通过不断创新、拓展市场和注重可持续发展,Caddock公司逐渐成为了电子行业中的佼佼者。然而,这些故事仅为虚构创作,实际发展情况可能有所不同。如需了解更多关于Caddock公司的真实发展历程和故事,建议查阅相关官方资料或行业报告。
作为一家有社会责任感的企业,意普(ESPE)公司始终关注环保和可持续发展。公司采用环保材料和生产工艺,减少了对环境的污染。同时,公司还积极参与社会公益活动,为社会做出了积极贡献。这些举措不仅提升了公司的社会形象,也为企业的长期发展奠定了良好的社会基础。
在快速发展的同时,CAMDENBOSS公司始终注重品质管理。公司建立了严格的质量管理体系,从原材料采购到产品生产的每一个环节都进行严格把控。此外,公司还积极引进先进的生产设备和技术,不断提升生产效率和产品质量。通过持续改进和优化,公司确保了产品品质的稳定性和可靠性。
随着业务的不断发展,安普康开始积极寻求市场拓展和战略合作的机会。公司在香港市场取得了显著的成绩后,决定进一步拓展内地市场。通过设立深圳安普康科技有限公司等分支机构,安普康逐步在内地市场建立了完善的销售网络和服务体系。同时,公司还与多家知名企业建立了长期合作关系,共同开拓市场、分享资源。这些合作不仅提升了安普康的市场地位,也为其未来的发展奠定了坚实的基础。
最近网站上有很多朋友问\"如何去采购,怎样才能做好采购\",希望我的这篇文章会对大家有所帮助! 采购分为很多类,最直接的两大类就是在终端运营商作采购(直接采购加工或生产某种产品的零件)和在贸易公司作采购.而我们这行主要是在贸易公司作采购!我 ...… 查看全部问答∨ |
一、引言 电动机调速是各行各业中电动机应用系统的必需环节。直流电动机因其磁链与转矩电流各自独立,不存在耦合关系,能够获得很好的调速范围和调速精度,静、动态特性均比较好而获得广泛应用。 交流(异步)电动机结构简单却因其磁链与电 ...… 查看全部问答∨ |
请大家推荐一款内置彩信模块的GPRS模块啊,TR800如何啊? 大家好,最近做一个GPRS彩信猫相关的课题,开始老板让用simcom的模块,说便宜,可是我要自己实现彩信协议,好晕啊。公司现在让我选择一款内置彩信模块的GPRS模块,这样我就可以不用自己实现彩信协议了,哪位大虾用过这方面应用给我推荐一款好吗?现 ...… 查看全部问答∨ |
QII可以产生.VO文件,对于功能仿真而言,我们可以注释掉其中一句关于sdo延迟文件加载的代码,也就是说可以将.vo变成针对功能仿真的文件而不加入时序内容,那么这样一来,可以用.VO文件做功能仿真,但是使用Modelsim直接编译verilog源文件,也可以做 ...… 查看全部问答∨ |
W801G模块外形小巧能够满足实际应用中对狭小空间的要求 ? 适合客户应用的SMT封装形式 ? 内嵌强大的TCP/IP协议栈 ? 基于成熟并已被验证的平台 ? GPRS multi-slot(Class 10/8)标准 ? GPRS mobile station(Class B)标准 ? 满足GSM 2/2+ ...… 查看全部问答∨ |
只要是这个系列的也行,这个芯片有68个引脚,但我在网上找到一个16c554的芯片资料却是18引脚的 请问哪位大侠有此芯片资料?项目比较紧急!先谢谢了!… 查看全部问答∨ |
使用max3232 双工时,收发出现干扰现象!望达人指点!! 具体现象是这样,当我从max3232向PC机发数据时,此时如果从上位机PC 发数据到max3232,那么刚才从max3232发送到PC的数据就会被干扰。 用示波器观察过了,确实有一个字节的数据失真了,后面的字节没错。而且捕捉到的这个失真的数据 ...… 查看全部问答∨ |
|
LPC1114/LPC11U14和LPC1343对比学习(五)UART 终于把支持3种芯片的板子焊接完成了,累死我了,可以继续学习下面的内容了。。。 开发板贴:https://bbs.eeworld.com.cn/viewthread.php?tid=299669&page=1&extra=page%3D1 LPC1114/LPC1343串口特点: 16字节收发 ...… 查看全部问答∨ |