当前位置:网站首页>关于TXE和TC标志位的小知识

关于TXE和TC标志位的小知识

2022-07-08 00:36:00 51CTO

TXE标志位

(针对 发送数据寄存器)

TXE为1:TDR里的数据全部移到了移位寄存器,且没有新的数据进TDR。

TXE为0:TDR里有数据,未空,则TXE为0。

TXE与"FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)"搭配使用来判断TDR中是否存在数据

      
      
int main ( void){
My_ _USART1() ;
USART_SendData ( USART1, 'H');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TXE) == RESET);
USART_SendData ( USART1,’K ');
while ( USART_GetFlagStatus ( USART1, USART_FLAG_TXE) == RESET);
USART_SendData ( USART1,” G ');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TXE) == RESET);
while( 1){}
}
//输出:H K G
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

TC标志位

(针对 发送数据寄存器)

TC为1:从TDR过来的数据全部被移送到TX引脚,且TDR里也没有新的数据。

TC为0:从TDR里过来的数据还没有全部移过来,或者之前TDR里的数据被移走了,但TDR里又来了新的数据。

      
      
int main ( void){
My_ _USART1() ;
USART_SendData ( USART1, 'H');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1,’K ');
while ( USART_GetFlagStatus ( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1,” G ');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
while( 1){}
}
//输出:K G
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

原因在于

关于TXE和TC标志位的小知识_TC

      
      
//第10/11执行的是先写入DR,再读取SR,步骤刚好相反,那么TC标志位就没有清0
//因为它不等于RESET,所以会立马执行下一行,这时候"K"会将“H”覆盖掉
//在执行发送"G"的时候就已经执行过上图中的操作,满足了相关的条件
  • 1.
  • 2.
  • 3.

解决方法:

  1. 在发送"K"前先读USART_SR;

      
      
int main ( void){
My_USART1() ;
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1, 'H');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1,’K ');
while ( USART_GetFlagStatus ( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1,” G ');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
while( 1){}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

  1. 软件清“0”,需要用到下面的函数

      
      
//清除标志位
void USART_ClearFlag( USART_TypeDef * USARTx, uint16_t USART_FLAG);
  • 1.
  • 2.
      
      
int main ( void){
My_USART1() ;
USART_ClearFlag( USART1, uint16_t USART_FLAG);
USART_SendData ( USART1, 'H');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1,’K ');
while ( USART_GetFlagStatus ( USART1, USART_FLAG_TC) == RESET);
USART_SendData ( USART1,” G ');
while ( USART_GetFlagStatus( USART1, USART_FLAG_TC) == RESET);
while( 1){}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

多组进行传输,需要查看对应的多个TXE标志位和一个TC标志位(TC为了确保最后一个字符从发送移位寄存器到TX)

重写USART_SendByte()使其可以重复写多个字符

      
      
void USART_SendByte( USART_TypeDef * USARTx, uint8_t Data){
assert_param( IS_USART_ALL PERIPH( USARTx));
assert_param( IS_USART_DATA( Data));
USARTx -> DR = ( Data & ( uint16_t) 0x01FF);
while ( USART_GetFlagStatus( USARTx, USART_FLAG_TXE) == RESET);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

发送字符串的函数

      
      
void USART SendString( USART_TypeDef * USARTx, char * str){
while( * str != '\0'){
USART_SendByte( USARTx, * str ++ );
while( USART_GetFlagStatus( USARTx, USART_FLAG_TC) == RESET);
}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

串口通信方式:轮询法、中断法。一般接收使用中断。

ITStatus值为1,表示可以读取数值了

ITStatus值为0,表示还不可以读取数值

可以通过while和if来进行判断


USART_GetITStatus()

USART_GetFlagStatus()

相同点

都是访问串口的SR状态寄存器


不同点

不仅会判断标志位是否置1,同时还会判断是否使能了相应的中断,所以在串口中断函数,通常使用该函数

只判断标志位,在没使能相应的中断时,通常使用该函数来判断标志位是否置1。

看懂一个库函数,需要结合具体的实例。

      
      
//不仅会判断标志位是否置1,同时还会判断是否使能了相应的中断,所以在串口中断函数,通常使用该函数
ITStatus USART_GetITStatus( USART_TypeDef * USART1, uint16_t USART_IT);
  • 1.
  • 2.

printf函数

在C语言中用于打印信息到控制台上。printf是单片机开发中调试的利器!

对printf底层函数进行重定向,使用fputc和fgetc

      
      
#include "stdio.h"
//fputc和fgetc是C语言的标准函数
//使用其FILE *f

//重定向c库函数printf到串口,重定向后可使用printf函数
int fputc( int ch, FILE * f){
USART_SendData ( USART1,( uint8_t) ch);
while ( USART_GetFlagStatus ( USART1,USART_FLAG_TXE) == RESET);
return ( ch);
}
//重定向c库函数scanf到串口,重写向后可使用scanf、getchar等 函数
int fgetc( FILE * f){
while ( USART_GetFlagStatus ( USART1,USART_FLAG_RXNE) == RESET);
return ( int) USART_ReceiveData ( USART1);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

printf()函数使用了半主机模式,会导致程序无法运行,因此要禁止这种模式

  1. 使用微库:使用微库时,就默认关闭了半主机模式
  1. 使用微库
  2. 引入stdio.h头文件
  3. 重写fputc和fgetc函数

关于TXE和TC标志位的小知识_TXE_02

可能会出现"FIFLE" is underfined,加上

      
      
//在usart.h中写入
typedef struct __FILE FILE
  • 1.
  • 2.

  1. 不使用微库,但是需要加上下面的话

      
      
#include "stdio.h"

#pragma import(__use_no_semihousting)
struct __FILE
{
int handle;
};
FILE __stdout;
_sys_exit( int x)
{
x = x;
}

//重定向c库函数printf到串口,重定向后可使用printf函数
int fputc( int ch, FILE * f){
USART_SendData ( USART1,( uint8_t) ch);
while ( USART_GetFlagStatus ( USART1,USART_FLAG_TXE) == RESET);
return ( ch);
}
//重定向c库函数scanf到串口,重写向后可使用scanf、getchar等 函数
int fgetc( FILE * f){
while ( USART_GetFlagStatus ( USART1,USART_FLAG_RXNE) == RESET);
return ( int) USART_ReceiveData ( USART1);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

  • 两种方法相同点:
  • 1都使用“stdio.h"头文件
  • 都需要重写printf底层函数,fputs和fgets.
  • 两种方法不同点:
  • 是否勾选“Use MicroLIB”

半主机模式:半主机模式是ARM单片机的一种调试机制,它需要通过仿真器来连接电脑和ARM单片机,并调用相应的指令来实现单片机向电脑显示器打印信息。

微库是为小内存嵌入式设备而设计,可以减少代码所占空间。

尽量少使用微库

  • 相对于C标准库而言,支持的功能更少,主要体现在对操作系统的支持上。
  • 标准的东西相对更可靠。

两个函数的相关内容

区别

int fputc(int ch,FILE *fp)函数

int fgetc(FILE *fp)函数

功能

将一个字符写入到文件中

从文件中读出一个字符

参数

ch要写入的字符,fp指向FILE结构的指针

fp指向FILE结构的指针

返回值

成功,返回该字符;遇到文件尾或读取错误时,返回EOF(-1)

成功,返回该字符;遇到文件尾或读取错误时,返回EOF(-1)

如何更好学习单片机

  • 首先找一个合适字节的教程
  • 动手实践!!

感谢海创电子的视频教学

海创电子:​ ​https://space.bilibili.com/93630735/?spm_id_from=333.999.0.0​

51单片机:​ ​https://www.bilibili.com/video/BV1vJ411X7iZ?spm_id_from=333.999.0.0&vd_source=cf352bf665894b2751d802dc81299dd8​

STM32单片机:​ ​https://www.bilibili.com/video/BV1N7411x7Yk?spm_id_from=333.999.0.0&vd_source=cf352bf665894b2751d802dc81299dd8​

原网站

版权声明
本文为[51CTO]所创,转载请带上原文链接,感谢
https://blog.51cto.com/u_15350455/5452621