您的位置 首页 资料

STM32串口中止的一些材料

在研究STM32串口接收发送中断的时候找到不少不错的资料,现在备份在这里。以供自己查阅,以及方便其他人。TC====TXE顺便预告下最近会写个有…

在研讨STM32串口接纳发送中止的时分找到不少不错的材料,现在备份在这儿。以供自己查阅,以及便利其他人。

TC====TXE

趁便预告下最近会写个有关串口处理数据的帖子,从查询和中止方面以及数据处理的方法,从行列以及FIFO方面写起。

SECTION1

SECTION2

先说TC。即TransmissionComplete。发送一个字节后才进入中止,这儿称为“发送后中止”。和本来8051的TI方法相同,都是发送后才进中止,需求在发送函数中先发送一个字节触发中止。发送函数如下

/*
功用:中止方法发送字符串.选用判别TC的方法.即判别发送后中止位.
输入:字符串的首地址
输出:无
*/
voidUSART_SendDataString(u8*pData)
{
pDataByte=pData;

USART_ClearFlag(USART1,USART_FLAG_TC);//铲除传输完结标志位,不然可能会丢掉第1个字节的数据.网友供给.

USART_SendData(USART1,*(pDataByte++));//必需求++,不然会把榜首个字符t发送两次
}

中止处理函数如下
/
*FunctionName:USART1_IRQHandler
*Description:ThisfunctionhandlesUSART1globalinterruptrequest.
*Input:None
*Output:None
*Return:None
*/
voidUSART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_TC)==SET)
{
if(*pDataByte==\0)//TC需求读SR+写DR方可清0,当发送到终究,到\0的时分用个if判别关掉
USART_ClearFlag(USART1,USART_FLAG_TC);//不然TC一向是set,TCIE也是翻开的,导致会不断进入中止.clear掉即可,不必关掉TCIE
else
USART_SendData(USART1,*pDataByte++);
}

}

其间u8*pDataByte;是一个外部指针变量

在中止处理程序中,发送完该字符串后,不必封闭TC的中止使能TCIE,只需求清掉标志位TC;这样就能防止TC==SET导致重复进入中止了。

串口初始化函数如下

/*
称号:USART_Config
功用:设置串口参数
输入:无
输出:无
回来:无
/
voidUSART_Config()
{
USART_InitTypeDefUSART_InitStructure;//界说一个包括串口参数的结构体

USART_InitStructure.USART_BaudRate=9600;//波特率9600
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8位数据位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//1位中止位
USART_InitStructure.USART_Parity=USART_Parity_No;//无校验
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流操控
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//输入加输出方法
USART_InitStructure.USART_Clock=USART_Clock_Disable;//时钟封闭
USART_InitStructure.USART_CPOL=USART_CPOL_Low;
USART_InitStructure.USART_CPHA=USART_CPHA_2Edge;
USART_InitStructure.USART_LastBit=USART_LastBit_Disable;
USART_Init(USART1,&USART_InitStructure);//设置到USART1

USART_ITConfig(USART1,USART_IT_TC,ENABLE);//TramsimssionComplete后,才发生中止.开TC中止有必要放在这儿,不然仍是会丢掉榜首字节

USART_Cmd(USART1,ENABLE);//使能USART1
}
这儿请问一个问题:开TC中止USART_ITConfig()假如放在我的USART_SendDataString()中再开,会丢掉字符串的榜首字节。有必要放在串口初始化函数中才不会丢。不知道为什么??

这儿笔者能够给出解说,你看下SECTION1就能够知道为什么呢,你这样做的原理和SECTION1解说的差不多,就相当于延时,而你后边没有丢掉数据的主要原因便是你代码中有这么一句USART_ClearFlag(USART1,USART_FLAG_TC);//铲除传输完结标志位,不然可能会丢掉第1个字节的数据.网友供给.

再说判别TXE。即TxDREmpty,发送寄存器空。当使能TXEIE后,只需TxDR空了,就会发生中止。所以,发送完字符串后有必要关掉,不然会导致重复进入中止。这也是和TC不同之处。

发送函数如下:
/*
功用:中止方法发送字符串.选用判别TC的方法.即判别发送后中止位.
输入:字符串的首地址
输出:无
*/
voidUSART_SendDataString(u8*pData)
{
pDataByte=pData;
USART_ITConfig(USART1,USART_IT_TXE,ENABLE);//只需发送寄存器为空,就会一向有中止,因而,要是不发送数据时,把发送中止封闭,只在开端发送时,才翻开。

}

中止处理函数如下:

/
*FunctionName:USART1_IRQHandler
*Description:ThisfunctionhandlesUSART1globalinterruptrequest.
*Input:None
*Output:None
*Return:None
/
voidUSART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_TXE)==SET)
{
if(*pDataByte==\0)//待发送的字节发到完毕NULL了
USART_ITConfig(USART1,USART_IT_TXE,DISABLE);//由于是发送寄存器空的中止,所以发完字符串后有必要关掉,不然只需空了,就会进中止
else
USART_SendData(USART1,*pDataByte++);
}

}

在串口初始化函数中就不必翻开TXE的中止了(是在发送函数中翻开的)如下:
/
称号:USART_Config
功用:设置串口参数
输入:无
输出:无
回来:无
/
voidUSART_Config()
{
USART_InitTypeDefUSART_InitStructure;//界说一个包括串口参数的结构体

USART_InitStructure.USART_BaudRate=9600;//波特率9600
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8位数据位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//1位中止位
USART_InitStructure.USART_Parity=USART_Parity_No;//无校验
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流操控
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//输入加输出方法
USART_InitStructure.USART_Clock=USART_Clock_Disable;//时钟封闭
USART_InitStructure.USART_CPOL=USART_CPOL_Low;
USART_InitStructure.USART_CPHA=USART_CPHA_2Edge;
USART_InitStructure.USART_LastBit=USART_LastBit_Disable;

USART_Init(USART1,&USART_InitStructure);//设置到USART1

USART_Cmd(USART1,ENABLE);//使能USART1

}

SECTION3

在USART的发送端有2个寄存器,一个是程序能够看到的USART_DR寄存器(下图中暗影部分的TDR),另一个是程序看不到的移位寄存器(下图中暗影部分TransmitShiftRegister)。

对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送完毕;对照下图,当TDR中的数据传送到移位寄存器后,TXE被设置,此刻移位寄存器开端向TX信号线按位传输数据,但由于TDR现已变空,程序能够把下一个要发送的字节(操作USART_DR)写入TDR中,而不必比及移位寄存器中一切位发送完毕,一切位发送完毕时(送出中止位后)硬件会设置TC标志。

另一方面,在刚刚初始化好USART还没有发送任何数据时,也会有TXE标志,由于这时发送数据寄存器是空的。

TXEIE和TCIE的含义很简略,TXEIE答应在TXE标志为1时发生中止,而TCIE答应在TC标志为1时发生中止。

至于什么时分运用哪个标志,需求依据你的需求自己决议。但我以为TXE答应程序有更富余的时刻填写TDR寄存器,确保发送的数据流不间断。TC能够让程序知道发送完毕的切当时刻,有利于程序操控外部数据流的时序。

SECTION4

总的来说,STM32单片机的串口仍是很好了解的,编程也不算杂乱。当然我更乐意期望其中止体系51单片机相同的简略。

关于接纳终端,便是RXNE了,这只在接纳完结后才发生,在碑文USART_ITConfig(USART1,USART_IT_RXNE,ENABLE)代码时不会进入ISR。但费事的便是发送有关的中止了:TXE或许TC,依据材料和测验的成果,TXE在复位后便是置1的,即在碑文USART_ITConfig(USART1,USART_IT_TXE,ENABLE)后会当即发生中止请求。因而这形成一个费事的问题:假如没有真实的发送数据,TXE中止都会发生,而且没有休止,这将占用很大部分的CPU时刻,乃至影响其他程序的运转!

因而主张的是在初始化时欠好启用TXE中止,只在要发送数据(尤其是字符串、数组这样的系列数据)时才启用TXE。在发送完结后当即将其封闭,避免引起不必要的费事。

关于发送,需求留意TXE和TC的不同——这儿简略描绘一下,假定串口数据寄存器是DR、串口移位寄存器是SR以及TXD引脚TXDpin,其联系是DR->SR->TXDpin。当DR中的数据转移到SR中时TXE置1,假如有数据写入DR时就能将TXE置0;假如SR中的数据悉数经过TXDpin移出而且没有数据进入DR,则TC置1。而且需求留意TXE只能经过写DR来置0,不能直接将其清零,而TC能够直接将其写1清零。

关于发送单个字符能够考虑不必中止,直接以查询方法完结。

关于发送字符串/数组类的数据,唯一要考虑的是只在终究一个字符发送后封闭发送中止,这儿能够分为两种状况:关于发送可显现的字符串,其用0x00作为完毕的,因而在ISR中就用0x00作为封闭发送中止(TXE或许TC)的条件;第二种状况便是发送二进制数据,那便是0x00~0xFF中心的恣意数据,就不能用0x00来判别完毕了,这时有必要知道数据的详细长度。

这儿简略剖析上面代码的碑文进程:TXE中止发生于前一个字符从DR送入SR,碑文作用是后一个字符送入DR。关于榜首种状况,假如是可显现字符,就碑文USART_SendData来写DR(也就清零了TXE),当终究一个可显现的字符从DR送入SR之后,发生的TXE中止发现要送入DR的是字符是0x00——这当然不可——此刻就封闭TXE中止,字符串发送进程就算完毕了。当然这时不能疏忽一个隐含的成果:那便是终究一个可显现字符从DR转入SR后TXE是置1的,但封闭了TXE中止,因而只需下次再舱位TXE中止就会当即进入ISR。关于第二种状况,其成果和榜首种的相同。

关于榜首种状况,其程序能够这么写:其间TXS是保存了要发送数据的字符串,TxCounter1是索引值:

extern__IOuint8_tTxCounter1;
externuint8_t*TXS;
extern__IOuint8_tTxLen;

voidUSART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_TXE)!=RESET)
{
if(TXS[TxCounter1])//假如是可显现字符
{USART_SendData(USART1,TXS[TxCounter1++]);}
else//发送完结后封闭TXE中止,
{USART_ITConfig(USART1,USART_IT_TXE,DISABLE);}
}
}

关于第二种状况,和上面的迥然不同,其间TXLen一共要发送的二进制数据长度:

voidUSART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_TXE)!=RESET)//对USART_DR的写操作,将该位清零。
{
if(TxCounter1{USART_SendData(USART1,TXS[TxCounter1++]);}
else//发送完结后封闭TXE中止
{USART_ITConfig(USART1,USART_IT_TXE,DISABLE);}
}
}

事实上榜首种状况是第二种的特别方法,便是说能够用第二种状况去发送可显现的字符——当然没人有闲心去数一句话里有多少个字母空格和标点符号!

在运用时,只需将TXS指向要发送的字符串或许数组,设置TxLen为要发送的数据长度,然后碑文USART_ITConfig(USART1,USART_IT_TXE,ENABLE)就当即开端发送进程。用户能够查看TxCounter1来确认发送了多少字节。比如以第二种状况为例:

uint32_t*TXS;
uint8_tTxBuffer1[]=”0123456789ABCDEF”;
uint8_tDST2[]=”ASDFGHJKL”;
__IOuint8_tTxLen=0x00;

TxLen=8;//发送8个字符,终究发送的是01234567
TXS=(uint32_t*)TxBuffer1;//将TXS指向字符串TxBuffer1
TxCounter1=0;//复位索引值
USART_ITConfig(USART1,USART_IT_TXE,ENABLE);//启用TXE中止,即开端发送进程
while(TxCounter1!=TxLen);//等候发送完结

TXS=(uint32_t*)TxBuffer2;//同上,终究发送的是ASDFGHJK
TxCounter1=0;
USART_ITConfig(USART1,USART_IT_TXE,ENABLE);
while(TxCounter1!=TxLen);

以上便是我以为的最佳计划,但串口中止方法数据有多长就中止多少次,我以为仍是占用不少CPU时刻,相比之下DMA方法就好多了,由于DMA发送字符串时最多中止两次(半传输完结,全传输完结),而且将串口变成相似16C550的器材。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/264804.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部