利用中断实现UART串口
串口收发 中断配置函数 usart1_irqhandler
函数原型:void USART1_IRQHandler(void)功能:处理 USART1 中断请求,包括接收和发送中断。
中断配置步骤:1.确定 USART1 中断向量号:这通常在芯片手册中指定,例如在 STM32F103系列中为IRQ_USART1。
2.在中断向量表中启用 USART1 中断:在中断向量表中将 USART1 中断向量号指向USART1_IRQHandler函数。
可以在启动代码中或使用函数NVIC_EnableIRQ()来完成此操作。
3.配置 USART1 中断优先级:使用函数NVIC_SetPriority()设置 USART1 中断的优先级。
优先级较高的中断将在低优先级中断之前得到响应。
4.配置 USART1 中断屏蔽:使用函数USART_ITConfig()或寄存器USART_CR1->RXNEIE和USART_CR1->TXEIE来配置 USART1 的接收(RXNE)和发送(TXE)中断。
中断服务例程:USART1_IRQHandler函数是 USART1 中断服务例程,它将在 USART1 发生中断时执行。
该函数通常会检查中断标志寄存器USART_SR中的标志位,以确定中断源并相应地采取操作。
以下是一个处理 USART1 接收和发送中断的示例中断服务例程:void USART1_IRQHandler(void){// 检查接收中断标志if(USART_GetITStatus(USART1, USART_IT_RXNE)!= RESET){// 读取接收数据uint8_t data = USART_ReceiveData(USART1);// 处理接收到的数据}// 检查发送中断标志if(USART_GetITStatus(USART1, USART_IT_TXE)!= RESET){// 发送数据USART_SendData(USART1, data);// 禁用发送中断(发送数据后)USART_ITConfig(USART1, USART_IT_TXE, DISABLE);}}。
UART串口通信—控制LED灯中断法
UART串口通信—控制LED灯(中断法)项目说明:1.通过串口来控制LED灯,发送1(十六进制)点亮LED灯(8个LED蓝灯),发送2(十六进制)关闭LED灯(8个LED蓝灯)。
2.通信速率:9600bps(即波特率为9600)3.串口通信采用中断的方法。
此项目练习的目的:(我们应掌握如下知识点)(1)熟悉串口中断相关寄存器的配置。
(2)学会串口中断的使用方法。
完整代码:#include "reg52.h"/*串口初始化:主要涉及寄存器配置*/void UartInit(void) //初始化uart{TMOD = 0X20; //定时器1定时器方式工作模式2,可自动重载的8位计数器常把定时/计数器1 以模式2 作为串行口波特率发生器SCON = 0X50; //串口选择工作模式1使能接收,允许发送,允许接收PCON = 0X00; //8位自动重载,波特率加倍TH1 = 0XFD; //用11.0592MHz波特率9600TL1 = 0XFD;TR1 = 1; //打开中时器/*由于我们采用中断法,所以我们还需要对串口中断相关的寄存器进行配置*/ES = 1;//串口中断EA= 1;//CPU总中断}//写串口中断响应的服务程序:void UartISR(void) interrupt 4{unsigned char TempDat;if (RI)/*查询串口是否接收到一个完整的数据*/{RI = 0;/*清除标志,准备下一次判断*/TempDat = SBUF;/*读取串口数据*/if (1 == TempDat)/*判断串口接收到的数据*/{P1 = 0;/*如果接收到的数据是1,则点亮8个LED蓝灯*/}} else if (2 == TempDat){P1 = 0xff;/*如果接收到的数据是2,则关闭8个LED蓝灯*/}} else{}}}void main(void){UartInit();/*调用串口初始化函数,进行相应的配置,如波特率等*/ while(1)//不用干啥事,一直等待就行。
STM8单片机 UART发送完成中断C语言程序
STM8S105发送完成中断#define TXRXBUF_SIZE 128uchar UART_RxTx[TXRXBUF_SIZE];volatile uchar UART_OutLen=0;volatile uchar TXRX_IndexR=0;volatile uchar TXRX_IndexW=0;void UART2_Init(void){//485 CS1控制PA_DDR |=1 << 6;PA_CR1 |=1 << 6;PA_CR2 &= ~( 1 <<6 );RS485_TX_EN=0; //设置为接收模式UART2_CR1=0x00;UART2_CR2=0x00;UART2_CR3=0x00;// 设置波特率,必须注意以下几点:// (1) 必须先写BRR2// (2) BRR1存放的是分频系数的第11位到第4位,// (3) BRR2存放的是分频系数的第15位到第12位,和第3位// 到第0位// 例如对于波特率位9600时,分频系数=2000000/9600=208// 对应的十六进制数为00D0,BBR1=0D,BBR2=00//UART2_BRR2=0x30;//UART2_BRR1=0xE8; //1K//UART2_BRR2=0x35;//UART2_BRR1=0x41; //1200UART2_BRR2=0x1B;UART2_BRR1=0xA0; //2400UART2_CR2=0x2c;//允许接收,发送,开接收中断//UART2_CR2=0x08; //发送使能}//------------方式二发送结束中断--------------------------------------#pragma vector=UART2_T_TC_vector__interrupt void UART2_T_TC(void){UART2_SR&= ~(1<<6); //清除送完成状态位if(UART_OutLen>0){UART2_DR=UART_RxTx[TXRX_IndexR];--UART_OutLen;if(++TXRX_IndexR >= TXRXBUF_SIZE){TXRX_IndexR=0;//FIFO回头}}else //发送结束{//UART_OutLen=TXRX_IndexR=TXRX_IndexW=0;//UART2_CR2 &= ~(1<<TCIEN);//关闭发送完成中断UART2_CR2 &= ~(1<<6);//关闭发送完成中断}}/************************************************************名称:Uart_IntSentBuf*功能:从串口UART0发送一组字节数据*入口参数:*p:待发的首个字节数据,len 发送个数*出口参数:返回1:发送成功* 返回0:发送失败*说明:在发送过程中,不阻塞CPU的运行。
STM8的C语言编程-UART应用
STM8的C语言编程(8)-- UART应用串口通讯也是单片机应用中经常要用到,今天的实验就是利用STM8的UART资源,来进行串口通讯的实验。
实验程序的功能是以中断方式接收串口数据,然后将接收到的数据以查询方式发送到串口。
程序代码如下,首先要对STM8的UART进行初始化,初始化时要注意的是波特率寄存器的设置,当求出一个波特率的分频系数(一个16位的数)后,要将高4位和低4位写到BRR2中,而将中间的8位写到BRR1中,并且必须是先写BRR2,再写BRR1。
同样也是利用ST的开发工具,生成一个C语言的框架,然后修改其中的main.c,同时由于需要用到中断服务,因此还要修改stm8_interrupt_vector.c。
修改后,编译连接,然后下载到开发板上,再做一根与PC机相连的线,把开发板的串口与PC机的串口连接起来,注意,2、3脚要交叉。
在PC机上运行超级终端,设置波特率为9600,然后每按下一个按键,屏幕上就显示对应的字符。
修改后的main.c和stm8_interrupt_vector.c如下:// 程序描述:初始化UART,以中断方式接收字符,以查询方式发送// UART通讯参数:9600bps,8位数据,1位停止位,无校验#include "STM8S207C_S.h"// 函数功能:初始化UART// 输入参数:无// 输出参数:无// 返回值:无// 备注:无void UART3_Init(void){LINUART_CR2 = 0; // 禁止UART发送和接收LINUART_CR1 = 0; // b5 = 0,允许UART// b2 = 0,禁止校验LINUART_CR3 = 0; // b5,b4 = 00,1个停止位// 设置波特率,必须注意以下几点://(1) 必须先写BRR2//(2) BRR1存放的是分频系数的第11位到第4位,//(3) BRR2存放的是分频系数的第15位到第12位,和第3位到第0位// 例如对于波特率位9600时,分频系数=2000000/9600=208// 对应的十六进制数为00D0,BBR1=0D,BBR2=00LINUART_BRR2 = 0;LINUART_BRR1 = 0x0d; // 实际的波特率分频系数为00D0(208) // 对应的波特率为2000000/208=9600 LINUART_CR2 = 0x2C; // b3 = 1,允许发送// b2 = 1,允许接收// b5 = 1,允许产生接收中断}// 函数功能:从UART3发送一个字符// 输入参数:ch -- 要发送的字符// 输出参数:无// 返回值:无// 备注:无void UART3_SendChar(unsigned char ch){while((LINUART_SR & 0x80) == 0x00); // 若发送寄存器不空,则等待 LINUART_DR = ch; // 将要发送的字符送到数据寄存器}main(){// 首先初始化UART3UART3_Init();_asm("rim"); // 允许CPU全局中断while(1) // 进入无限循环{}}// 函数功能:UART3的接收中断服务程序// 输入参数:无// 输出参数:无// 返回值:无@far @interrupt void UART3_Recv_IRQHandler (void){unsigned char ch;ch = LINUART_DR; // 读入接收到的字符 UART3_SendChar(ch); // 将字符发送出去}/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void @far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};@far @interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is recommended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */extern @far @interrupt void UART3_Recv_IRQHandler();struct interrupt_vector const _vectab[] ={0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, NonHandledInterrupt}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, UART3_Recv_IRQHandler}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};2010-8-6程序备份/* MAIN.C file** Copyright (c) 2002-2005 STMicroelectronics*/#include "STM8S103f3p.h"/////////////////////////////////////////void Init_UART1(void){UART1_CR1=0x00;UART1_CR2=0x00;UART1_CR3=0x00;// 设置波特率,必须注意以下几点:// (1) 必须先写BRR2// (2) BRR1存放的是分频系数的第11位到第4位,// (3) BRR2存放的是分频系数的第15位到第12位,和第3位// 到第0位// 例如对于波特率位9600时,分频系数=2000000/9600=208// 对应的十六进制数为00D0,BBR1=0D,BBR2=00UART1_BRR2=0x00;UART1_BRR1=0x0d;UART1_CR2=0x2c;//允许接收,发送,开接收中断}///////////////////////////////////////////void UART1_sendchar(unsigned char c){while((UART1_SR&0x80)==0x00);UART1_DR=c;}////////////////IO初始化////////////////////void init_gpio(void){//将pb5设置成推挽输出PB_DDR = 0x20; //数据方向PB_CR1 = 0x20; // 上拉、悬空PB_CR2 = 0x00;}/////////////////////////////////////////////main(){unsigned char i=0;init_gpio();Init_UART1();_asm("rim");//开中断,sim为关中断while (1);}//将收到的数据再发送出去@far @interrupt void UART1_Recv_IRQHandler (void) {unsigned char ch;ch=UART1_DR;UART1_sendchar(ch);PB_ODR^=0x20;return;}/*/////////////////////////////////////串口发送程序///////////////////////////////////////#include "STM8S103f3p.h"void delay(unsigned int ms){unsigned char i;while(ms != 0){for(i=0;i<250;i++){}for(i=0;i<75;i++){}ms--;}}/////////////uart初始化///////////////////void init_uart1(void){UART1_CR1=0x00;UART1_CR2=0x00;UART1_CR3=0x00;// 设置波特率,必须注意以下几点:// (1) 必须先写BRR2// (2) BRR1存放的是分频系数的第11位到第4位,// (3) BRR2存放的是分频系数的第15位到第12位,和第3位// 到第0位// 例如对于波特率位9600时,分频系数=2000000/9600=208// 对应的十六进制数为00D0,BBR1=0D,BBR2=00UART1_BRR2=0x00;UART1_BRR1=0x0d;UART1_CR2=0x2c; //允许接收,发送,开接收中断}//////////////uart发送程序//////////////////////void uart1_sendchar(unsigned char c){while((UART1_SR & 0x80)==0x00);UART1_DR=c;}//////////////初始化A/D模块/////////////////////void init_ad(void){ADC_CR2 = 0x00; // A/D结果数据左对齐ADC_CR1 = 0x00; // ADC时钟=主时钟/2=1MHZ// ADC转换模式=单次// 禁止ADC转换ADC_CSR = 0x03; // 选择通道3ADC_TDRL = 0x20;}///////////////读AD值/////////////////////unsigned char read_ad(void){unsigned char i=0;ADC_CR1 = 0x01; // CR1寄存器的最低位置1,使能ADC转换for(i=0;i<100;i++);// 延时一段时间,至少7uS,保证ADC模块的上电完成ADC_CR1 = ADC_CR1 | 0x01;// 再次将CR1寄存器的最低位置1// 使能ADC转换while((ADC_CSR&0x80)==0); // 等待ADC结束i = ADC_DRH; // 读出ADC结果的高8位return(i);}////////////////IO初始化////////////////////void init_gpio(void){//将pb5设置成推挽输出PB_DDR = 0x20; //数据方向PB_CR1 = 0x20; // 上拉、悬空PB_CR2 = 0x00;}/////////////////////////////////////////////main(){unsigned char i=0;init_uart1();init_ad();init_gpio();while (1){delay(1000);i=read_ad();uart1_sendchar(i);PB_ODR^=0x20;}}/////////////////////////////////////////////////*/友情提示:范文可能无法思考和涵盖全面,供参考!最好找专业人士起草或审核后使用,感谢您的下载!。
HAL库UART的几个常用函数讲解+中断处理过程讲解
HAL 库UART 的⼏个常⽤函数讲解+中断处理过程讲解【开源】做了⼀个STLINK/V2-UART ⼆合⼀编程器【实战经验】UART 应⽤异常案例分析HAL 库是⽐较全⾯的,封装⽐较彻底的,也是功能⽐较强⼤的。
使⽤HAL 库,我们直接调⽤它的API 函数,不⽤关⼼它的底层操作过程。
使⽤HAL 库,省去了好多繁琐的处理过程,不再需要我们⾃⼰写如等待等过程。
HAL 库也包含如Ethernet 、USB 等⾼级外设的驱动。
对于初接触它的⼈来说,尤其是⽤惯了标准库的⼈,总会有各种不适应和排斥感。
就拿UART 来说,我们通过中断⽅式接受或发送数据。
如果仿真调试的话,会发现UART 有开关中断的现象,⽽不是中断⼀直开着。
下⾯,就讲解UART 常⽤函数以及中断处理过程。
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);串⼝发送,串⼝发送,发送指定长度的数据。
如果超时没发送完成,则不再发送,返回超时标志发送指定长度的数据。
如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT )。
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData,uint16_t Size, uint32_t Timeout);串⼝接收,串⼝接收,接收指定长度的数据。
如果超时没接收完成,则不再接收数据到指定缓冲区,接收指定长度的数据。
如果超时没接收完成,则不再接收数据到指定缓冲区,返回超时标志(HAL_TIMEOUT )。
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);串⼝中断发送,以中断⽅式发送指定长度的数据。
串口中断UART0
串口中断UART0关于串口0终端服务程序irq_uart0()iir?u0iir?答:u0iir是接收器缓存寄存器u0rbr:接收器缓存寄存器访问时,先要设定u0lcr的除数锁存访问位(dlab)为0。
因为,u0dll与u0rbr/u0thr在同一地址上。
当dlab=1时,选择u0dll和u0dlm(u0dlm和u0ier位于同一地址);当dlab=0时,选择u0rbr/u0thr和u0ier。
U0dll和u0dlm:形成一个16位除数。
vpb时钟(pclk)是产生波特率的时钟源,波特率时钟源必须是波特率的16倍,于是有:baud_rate=pclk/(16*设定的除数)UART0中断:有4个中断,分别是:RBR中断;中断;接收线路中断;其中rbr中断里面包含有2个中断:数据可用rda中断和接收超时cti中断。
faq一:1.什么是RDA中断?当接收的有效数据到达接收fifo设置寄存器(u0fcr)中设置的触发点时,rda中断被激活。
U0fcr[7:6]=00触发点0(1字节);U0fcr[7:6]=01触发点1(4字节);U0fcr[7:6]=01触发点2(8字节);U0fcr[7:6]=01触发点1(14字节);中断后,u0iir[3:0]内容为0100。
如果发生中断后,读一下u0rar寄存器,那么就会得到最早到达的数据。
这时,fifo中的有效数据小于预定触发点,清零rda中断。
该中断的优先级为2。
2.什么是CTI中断?在接收fifo中,有效的数据少于触发个数时,但至少有一个时,如果长时间没有数据到达,将触发cti中断。
这里所说的“长时间”是指在接收3.5~4.5个字节所需要的时间。
发生中断,则u0iir[3:0]内容为:1100。
在中断后,若从u0rbr中读取接收fifo中的数据,或者有新的数据送入接收fifo中,这都将清零cti中断。
该中断的优先级为2。
3.什么是中断?thre中断是发送中断。
中断方式下进行串口通讯的正确方法
中断方式下进行串口通讯的正确方法在计算机和外设之间进行串口通信时,常见的方式有中断方式和轮询方式。
中断方式下进行串口通讯的正确方法如下:1.硬件设置:首先,需要确保串口的硬件设置正确。
包括串口的波特率、数据位、停止位、校验位等设置要和外设一致。
另外,还需要设置中断控制寄存器,使其可以响应串口中断。
2.中断初始化:在程序开始时,需要进行中断初始化的操作。
具体的步骤包括开启串口中断、清除中断标志、设置中断优先级等。
这些步骤的具体操作可以参考串口的芯片手册或者开发板的文档。
3.中断服务程序:中断服务程序是在串口中断发生时被调用的,用于处理接收和发送数据。
在中断服务程序中,通常需要进行以下操作:-接收数据处理:通过读取串口接收缓冲区中的数据来获取接收到的数据。
可以使用逐字节读取的方式或者一次读取多个字节的方式,具体取决于应用需求。
处理完接收到的数据后,可以进行一些解析、存储或者其他处理操作。
-发送数据处理:如果需要发送数据,可以在中断服务程序中写入数据到串口发送缓冲区。
同样,可以一次发送一个字节或者一次发送多个字节,具体取决于应用需求。
在发送数据期间,可以再次触发发送中断以继续发送下一个字节。
4.中断优先级设置:如果系统中有多个中断,需要按照优先级来设置中断。
一般来说,串口中断应该具有较高的优先级,以确保及时响应和处理数据。
中断优先级的设置可以在中断初始化中设置。
5.接收和发送缓冲区管理:在进行中断方式的串口通讯时,需要使用接收和发送缓冲区来保存数据。
在中断服务程序中,需要管理这些缓冲区的读写操作。
接收缓冲区需要进行读取操作,确保及时读取接收的数据;发送缓冲区需要进行写入操作,将需要发送的数据写入到缓冲区中。
6.数据同步:在进行中断方式的串口通讯时,需要注意数据同步的问题。
特别是当数据的接收和发送同时进行时,需要确保数据的同步操作。
比如,在接收到数据后,可以使用信号量或者标志位来通知应用程序进行接收数据处理,而不是在中断服务程序中直接处理。
UART通信程序_中断方法
int int_flag; int_flag++; UART0_SendByte(rebuf[send_pointer]); } else { send_pointer=0; } } if(int_flag==4) { rebuf[re_pointer]=U0RBR; if (re_pointer>=10) { UART0_SendByte(rebuf[0]); re_pointer=0; } } VICVectAddr=0; } re_pointer++;
通信参数设置
void UART0_Init(void){ uint16 Fdiv; PINSEL0 = 0x00000005; U0LCR = 0x83; Fdiv = (Fpclk / 16) / 9600; U0DLM = Fdiv / 256; U0DLL = Fdiv % 256; U0LCR = 0x03; }
UART通信程序中断实现方法 通信程序中断实现方法
——发送中断与接收中断 发送中断与接收中断
声明: 声明:本文著作权归电子科技大学中山学院嵌入式系统实验室所有 著作人: 著作人:邓春健
UART通信程序 通信程序 ——发送中断程序 发送中断程序
回忆: 回忆:P297页使用查询方式从串口发送多个字节数 页使用查询方式从串口发送多个字节数 据
uart中断触发方式
uart中断触发方式
UART(通用异步收发器)是一种串行通信协议。
在单片机中,我们经常使用UART作为与其他设备或芯片进行通信的接口。
当接收到数据时,有两种方式可以将其传递给单片机处理:轮询和中断。
在轮询方式下,单片机会不断地检查UART接收寄存器是否有新的数据。
若存在数据,单片机会将其读取并进行处理。
这种方式会浪费大量的处理器时间,并且无法及时响应接收到的数据。
中断方式则是一种更高效的方式。
它允许单片机在接收到数据时立即停止正在执行的任务,转而处理接收到的数据。
使用中断方式可以大大减少CPU的轮询时间,提高系统效率。
UART中断可以由两种方式触发:接收中断和发送中断。
接收中断触发方式如下:UART会接收到一帧数据后,将其存储在接收寄存器中。
当接收缓冲区中有数据时,这时如果启用了接收中断,则将触发中断。
中断程序将从接收寄存器读取数据,然后进行进一步逻辑处理。
发送中断触发方式如下:当发送寄存器为空时,这时如果启用了发送
中断,则将触发中断。
中断程序将从发送缓冲区中读取下一个字节,并将其写入发送寄存器,以便于发送。
总之,在单片机中使用UART进行通信时,中断方式是一种更高效的方式。
通过观察UART的接收缓冲区和发送寄存器状态,可以确定何时触发中断并执行相应的中断程序。
通过这种方式可以高效地处理数据,提高系统效率。
利用中断实现UART串口
利用中断实现UART串口串口通信是计算机与外部设备进行数据传输的一种方式,可以使用各种方法实现。
其中一种常见的实现方式是使用中断来实现UART串口通信。
UART(Universal Asynchronous Receiver/Transmitter)是一种通用的异步串行通信接口,广泛应用于计算机和外部设备之间的数据传输。
在UART通信中,数据以字节为单位进行传输,每个字节都包含一个起始位、8个数据位、可选的奇偶校验位和一个停止位。
UART通信可以通过中断来实现,中断在接收和发送数据时起到相应的作用。
下面是实现UART串口通信的步骤:1.初始化串口参数:包括波特率、数据位、校验位、停止位等。
2.初始化中断控制器:将串口接收和发送的中断使能。
3.编写中断处理函数:包括接收和发送中断处理函数。
接收中断处理函数的基本流程如下:-判断接收缓冲区是否有数据可读,如果没有则直接返回。
-读取接收缓冲区的数据,并做相应的处理。
发送中断处理函数的基本流程如下:-判断发送缓冲区是否有空间可写,如果没有则直接返回。
-将要发送的数据写入发送缓冲区,并触发发送操作。
在中断处理函数中,需要使用适当的数据结构来保存接收和发送的数据,以及相应的状态信息。
除了中断处理函数,还需要编写主程序来初始化串口和中断控制器,并监控串口的数据传输。
主程序可以使用循环来接收和发送数据,或者等待外部事件触发中断。
总结来说,通过使用中断来实现UART串口通信,可以实现数据的异步传输和高效处理,提高系统的响应速度和并发性。
同时,中断的使用也能减少对CPU资源的占用,提高系统的性能。
gd32串口中断函数
GD32是中国兆易创新(GigaDevice)推出的一款通用微控制器(MCU),其串口(UART)模块提供了一些中断功能。
以下是一个基本的GD32串口中断函数的示例:c复制代码#include"gd32f10x.h"UART_HandleTypeDef huart1;void UART1_Init(void){huart1.Instance = UART1;huart1.Init.BaudRate = 9600;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if(HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}}void UART1_IRQHandler(void){/* Check if the UART1 global interrupt flag is set */if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_GLBLINTR) != RESET){/* Check if the UART Rx Underrun interrupt is set */if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXUDR) != RESET){/* Clear the UART Rx Underrun flag */__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXUDR);/* Re-enable the UART Rx Interrupt */__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);}/* Check if the UART Parity Error interrupt is set */if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_PERR) != RESET){/* Clear the UART Parity Error flag */__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_PERR);/* Re-enable the UART Parity Error Interrupt */__HAL_UART_ENABLE_IT(&huart1, UART_IT_PARE);}/* Check if the UART Framing Error interrupt is set */if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_FERR) != RESET) {/* Clear the UART Framing Error flag */__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_FERR);/* Re-enable the UART Framing Error Interrupt */__HAL_UART_ENABLE_IT(&huart1, UART_IT_FE);}/* Check if the UART Transmission complete interrupt is set */ if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) != RESET){/* Clear the UART Transmission complete flag */__HAL。
USART串口通信,中断方式,一分钟从菜鸟到大师(完整版)
USART串⼝通信,中断⽅式,⼀分钟从菜鸟到⼤师(完整版)嵌⼊式系统中应⽤最⼴泛的⼀种通讯设备,只要三根线(TX,RX,GND),合适低速长距离通讯。
发送和接收的控制流程如下:1.初始化串⼝包括使能串⼝时钟,使能发送和接收,定义引脚,波特率,数据位长度,奇偶校验⽅式,停⽌位位数。
使能串⼝模块接收中断,此时不能使能发送中断。
使能全局串⼝中断并设置优先级。
定义⼀个接收超时定时器,设置好超时值,并使能超时中断,这此定时器是关闭状态。
2. 发送定义控制结构,typedef struct txCtrl{ u8 buf[TX_SIZE],//根据最长发送帧定义⼤⼩ u8 idx; u8 len;//实际数据长度}txCtrl_t;txCtrl_t txCtrl;2.1 数据准备将发发送的数据装到txCtrl.buf,txCtrl.len=数据长度,txCtrl.idx=0。
2.2 启动发送uartSend(){ //马上触发中断使能发送缓冲器空中断;}3. 接收接收数据时会遇到⼀个问题,就是接到数据字节数是多少?⼀个帧数据接接收到什么时候才算结束?解决这个问题,我们要使⽤到定时器。
其原理是,接收到数据时,使能定时器,并设置超时时间为串⼝传输⼀个或⼏个字节的时间,注意,这个时间是随波特率变化的。
如果定时器超时了,意味差这个帧结束了。
⽐如9600的波特率,起始位1,停⽌位1位,数据位8位,奇偶校验位0位,传输⼀个字节共10位的时间⼤约 10/9600=1ms.定义控制结构,typedef struct rxCtrl{ u8 buf[RX_SIZE],//根据最长接收帧定义⼤⼩ u8 len;//接收到的数据长度}rxCtrl_t;rxCtrl_t rxCtrl;4. 中断服务有两个中断服务要处理,⼀个是串⼝中断,⼀个是接收定时器超时中断。
串⼝中断void usartISR(void){ if( 发送结束中断标志==1 ) { 清除此标志关闭发送结束中断功能 } if( txCtrl.len>0 ) { //把数据装⼊串⼝数据寄存器 DR = txCtrl.buf[txCtrl.idx++]; txCtrl.len--; //最后⼀个字节 if( txCtrl.len == 0 ) { 关闭发送缓冲器空中断,使能发送注意⚠ ,启动发送是使能发送缓冲器空中断,在发送最后⼀字节时关闭并使能发送完成中断,这样效率最⾼。
使用STM32CubeMX实现中断模式下的串口收发
单击 UART 按钮弹出设置窗口。
Baud Rate :波特率:此后生成的初始化程序会对波特率和 APB 总线频率进行自动换算。 Word Length:字长
Parity:校验位 Stop Bits:停止位 Data Direction:设置发送接收模式 Over Sampling:对接收信号的采样倍率。如果软件模拟串口一般 3 次采样/位就够了,这里 默认即可。
C)串口接收的实现方法 在 main.c 的 while(1)前执行
if(HAL_UART_Receive_IT(&huart5,aRxBuffer,1)!=HAL_OK)Error_Handler();开启接收中 断,准备接收。
在 main.c 中重写串口接收回调函数如下: void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {
Uart5Ready_R = SET; Rx_Num_UART5 = ++Rx_count_UART5; Rx_count_UART5 = 0; } else Rx_count_UART5++; HAL_UART_Receive_IT(&huart5,aRxBuffer,1); //开启下一次接收中断 } } 在此回调函数中,每次接收到的字节 aRxBuffer[0]都会存入 Rxbuff[ ] ,Rx_count_UART5 自动加 1。结束字节为 0x0D 0x0A。一组字节接收结束后,Uart5Ready_R 将赋值为 SET, 接收字节数保存在 Rx_Num_UART5。 因为在调用 HAL_UART_IRQHandler(&huart5);时,调用了 UART_Receive_IT(),其中 执行了 __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE),所以接收中断必须在回调函 数中重新开启,最简单的就是重复调用 HAL_UART_Receive_IT(&huart5,aRxBuffer,1)了。
UART串口通讯(中断)
• UART接收FIFO缓冲区
UnRSR
• UART0、UART1各含有1 个16字节的接收FIFO缓冲 区。 • 软件设置接收FIFO缓冲区 的触发字节。
RXD
接收FIFO
UnFCR
UnRBR
UART FIFO控制寄存器 位 功能 7 6 [5 : 3] — 2 复位TxFIFO 1 复位RxFIFO 0 使能FIFO Rx触发点设置
中断服务函数
• void UART0_IRQHandler(void) • {int i; • switch(U0IIR & 0x0f) • { • case 0x04: //RxFIFO达到14字节 • for(i=0;i<13;i++) RcvBuf[RcvP++]=U0RBR; break; • case 0x0c: //接收超时, 表示数据结束 • while(U0LSR & 0x01) RcvBuf[RcvP++]=U0RBR; • RcvL=RcvP; //一帧数据结束标志 • RcvP=0; break; //准备接受下一数据 • case 0x02: //发送缓冲器空 • if(TxdP==TxdL) {U0IER = 0X05; // THRE中断禁止 • TxdL=TxdP=0;} • else {for(i=16;i>0;i--) {if(TxdP==TxdL) break; //发送字符完 • else U0THR = TxdBuf[TxdP++];} } break; • case 0x06: //状态中断 • RcvL=U0LSR; //读状态, 清除错误标志 • RcvP=RcvL=TxdP=RxdL=0; break; • } }
STM32串口中断接受数据教程
STM32串口中断接受数据教程在STM32系列微控制器中,使用串口接收数据可以通过中断方式实现,这种方式对于实时性要求较高的应用非常有用。
本教程将介绍如何在STM32中配置串口接收中断,并编写相应的中断服务程序来处理接收到的数据。
首先,我们需要初始化串口硬件和中断。
在STM32CubeIDE中,可以使用CubeMX来生成初始化代码。
在"Pinout & Configuration"选项卡中,选择所需的串口引脚,并设置相应的参数(如波特率、数据位、停止位等)。
然后,在"Configuration"选项卡中,启用串口的中断功能。
接下来,需要在代码中创建串口接收中断的回调函数。
在CubeMX生成的代码中,可以找到一个名为"USARTx_IRQHandler"的函数,其中"x"是串口的编号。
在这个函数中,可以添加处理接收数据的代码。
在回调函数中,可以使用HAL库提供的函数来判断是否接收到了新的数据。
例如,可以使用"__HAL_UART_GET_FLAG"函数来检查接收寄存器非空标志位,并使用"__HAL_UART_CLEAR_FLAG"函数清除该标志位。
然后,可以使用"__HAL_UART_GET_IT_SOURCE"函数来检查是否使能了接收中断。
如果使能了接收中断且接收寄存器非空,可以使用"__HAL_UART_CLEAR_IT"函数清除接收中断标志位,并使用"HAL_UART_RxCpltCallback"函数来处理接收到的数据。
在回调函数中,可以通过使用"HAL_UART_Receive_IT"函数来继续接收更多的数据。
此函数可以在接收完成后自动调用回调函数,以便连续接收数据。
在主函数中,可以使用"HAL_UART_Receive_IT"函数启动接收数据。
51单片机uart停止位2位的实现
51单片机uart停止位2位的实现51单片机是一种广泛应用于嵌入式系统中的单片机芯片,具有高性能、低功耗和易于编程的特点。
其中,UART(Universal Asynchronous Receiver/Transmitter)是一种通用异步收发器,常用于实现串口通信。
本文主要探讨如何在51单片机中实现UART停止位为2位的功能。
UART通信是一种通过串行线路进行数据传输的方式,包括发送和接收两个过程。
在UART通信中,数据的传输是以数据帧为单位进行的,每个数据帧由起始位、数据位、校验位和停止位组成。
停止位是数据帧的最后一位,用于告诉接收方数据帧的结束位置。
通常情况下,UART通信中的停止位为1位,即数据帧的最后一位是一个高电平信号。
但有些特殊情况下,需要使用停止位为2位的UART通信。
实现UART停止位为2位的功能需要对51单片机的串口寄存器进行相应的配置。
首先,需要设置串口的工作模式为异步模式,并选择相应的波特率。
然后,需要设置串口的数据位数、校验方式和停止位数。
在51单片机中,UART的寄存器位于特殊功能寄存器SFR中,包括TCON、TMOD、TH1、TL1、SCON等寄存器。
具体的配置步骤如下:1. 设置串口工作模式:将TCON寄存器中的SM0和SM1位分别设置为1和0,表示选择8位异步模式。
2. 设置波特率:串口通信需要设定一个固定的波特率,用于控制数据传输的速度。
在51单片机中,波特率的设定通过设置TH1和TL1寄存器的值来实现。
具体的计算公式是:波特率 = 1 / (2 * (256 - TH1) * 12 / 机器周期)。
在这里,机器周期是指51单片机的工作周期,一般为12个机器周期。
根据需要设定的波特率,通过计算可以得到TH1和TL1的值。
3. 设置数据位数、校验方式和停止位数:通过设置SCON寄存器中的相应位来实现。
其中,数据位数可以选择为8位或9位;校验方式可以选择为无校验、奇校验或偶校验;停止位数可以选择为1位或2位。
STM32中断法USART串口简单使用
STM32中断法USART串口简单使用
1.初始化USART外设:首先需要在STM32的寄存器中对USART进行初始化。
具体的步骤包括:选择时钟源、配置波特率、设置数据长度、设置停止位、设置校验位等。
这些设置都可以在USART的控制寄存器中进行。
2.配置串口引脚:需要将USART的引脚与STM32的GPIO引脚进行连接。
具体的配置方法包括将GPIO引脚设置为复用功能,并且选择对应的USART信号。
3.编写中断服务函数:为了使用中断方式接收和发送数据,需要编写中断服务函数。
中断服务函数通常由硬件自动调用,当USART接收到数据或发送数据完成时触发。
在中断服务函数中,我们可以读取接收到的数据或者发送下一个数据。
4.使能中断:要使能USART的串口接收中断,需要在USART的控制寄存器中设置相应的位。
通常有RXNE和TC中断位,分别表示接收缓冲区非空和发送完成。
5.启动USART:启动USART外设,使其处于工作状态。
可以在相应的控制寄存器中设置TE(发送使能)和RE(接收使能)位。
6.外部中断配置:在STM32中,需要在NVIC寄存器中配置和使能USART接收中断的优先级。
这样才能通过中断向量表触发中断。
通过上述步骤,可以完成USART串口的简单使用,实现数据的接收和发送。
在编写中断服务函数时,可以根据实际需求进行数据处理,例如打印接收的数据或根据接收到的数据触发其他功能。
STM32HAL库使用中断实现串口接收不定长数据
STM32HAL库使用中断实现串口接收不定长数据要在STM32HAL库中实现串口接收不定长数据超过1200字,您可以使用中断来接收。
以下是一个简单的示例代码,演示了如何设置串口接收中断,并处理超过1200个字的数据:```c#include "stm32xxxx.h" // 根据您的STM32型号进行包含适当的头文件#define RX_BUFFER_SIZE 2000 // 定义接收缓冲区的大小//定义接收缓冲区和相关变量uint8_t rxBuffer[RX_BUFFER_SIZE];volatile uint16_t rxIndex = 0;volatile uint8_t rxDataAvailable = 0;//初始化串口void UART_Ini//串口GPIO引脚配置//串口时钟配置//串口配置//使能接收中断__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);//中断处理函数void USART1_IRQHandler(void)if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)) rxBuffer[rxIndex++] = huart1.Instance->DR;if (rxIndex >= RX_BUFFER_SIZE)//接收超过1200字,进行处理//在这里添加您的处理代码//重置接收缓冲区和相关变量rxIndex = 0;rxDataAvailable = 0;} else//未达到1200字,继续接收rxDataAvailable = 1;}}int main(void)//初始化硬件//...//初始化串口UART_Init(;while (1)if (rxDataAvailable)//执行接收数据处理//在这里添加您的处理代码//重置接收缓冲区和相关变量rxIndex = 0;rxDataAvailable = 0;}//执行其他任务//...}```在上述代码中,我们首先定义了一个接收缓冲区 `rxBuffer`,并使用 `rxIndex` 变量来跟踪接收到的字节数。
uart帧中断实现原理
UART(Universal Asynchronous Receiver/Transmitter)是一种常见的串行通信接口,用于在计算机和外部设备之间传输数据。
UART帧中断是一种实现方式,用于在接收到完整的UART 数据帧时触发中断。
UART帧中断的实现原理如下:
1. 配置UART控制器:首先需要配置UART控制器的相关寄存器,包括波特率、数据位数、停止位数、校验位等参数。
这些参数需要与发送方设备保持一致,以确保正确的数据传输。
2. 接收数据:当UART控制器接收到一个字节的数据时,会将其存储在接收缓冲区中。
接收缓冲区通常是一个FIFO (First-In-First-Out)队列,用于存储接收到的数据。
3. 检测帧结束:UART帧通常由起始位、数据位、校验位和停止位组成。
在接收数据时,UART控制器会检测起始位和停止位的边沿,以确定一个完整的数据帧是否接收完成。
4. 触发中断:当UART控制器检测到一个完整的数据帧时,会触发一个中断信号。
中断信号会通知处理器,表示有新的
数据可供处理。
5. 中断处理程序:一旦中断信号被触发,处理器会跳转到预先定义的中断处理程序。
中断处理程序会读取接收缓冲区中的数据,并进行相应的处理,例如存储到内存中或进行进一步的处理。
需要注意的是,UART帧中断的实现可能会因不同的硬件平台和操作系统而有所差异。
上述步骤仅为一般的实现原理,具体的实现方式可能会有所不同。
STM32HAL库使用中断实现串口接收不定长数据
STM32HAL库使⽤中断实现串⼝接收不定长数据 以前⽤DMA实现接收不定长数据,DMA的⽅法接收串⼝助⼿的数据,全部没问题,不过如果接收模块返回的数据,⽽这些数据如果包含回车换⾏的话就会停⽌接收,例如接收:AT\r\nOK\r\n,就只能接收到AT\r,导致没有接收完成,具体原因还没搞懂,有了解的,希望可以告知⼀下,DMA不定长接收⽅法传输门:。
好了,不多说了,现在进⼊正⽂。
⾸先建⽴⼀个STM32Cumebx的⼯程,打开串⼝中断,完成配置,具体的配置流程就不细说了,没什么难度就只是打开串⼝跟中断⽽已。
⽣成⼯程代码后,先定义好⼀些变量://串⼝4中断接收定义#define MAX_RECV_LEN 1024 //设定可以接收的最⼤字节uint8_t msg_buff[MAX_RECV_LEN] = {0}; //接收缓存区uint8_t * msg = msg_buff; //定义⼀个指针指向接收缓存区int flag = 0; //接收完成标志int len_u4=0; //数据长度记录 接着重写串⼝接收回调函数/*重写串⼝接收回调函数*/void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle){uint8_t ret = HAL_OK;msg++;len_u4++;//数据长度计数if( msg == msg_buff + MAX_RECV_LEN){msg = msg_buff;}do{ret = HAL_UART_Receive_IT(UartHandle,(uint8_t *)msg,1);}while(ret != HAL_OK);if(*(msg-1) == '\n') //接收以\n为结尾字符,则表⽰接收完成{flag = 1;}} 最后在main函数⾥⾯编写接收后的逻辑,注意要在while(1){ }前打开串⼝接收中断int main(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration----------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init(); MX_DMA_Init(); MX_USART3_UART_Init();MX_UART4_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE *///⾃⼰添加代码部分:while前打开串⼝中断接收HAL_UART_Receive_IT(&huart4, (uint8_t *)msg, 1); //开启第⼀次中断while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///======⾃⼰添加代码部分=========if (flag == 1){printf("msg_buff = %s ;len = %d\r\n",msg_buff,len_u4); HAL_Delay(100); //加延时,保证接收到数据过长的时候,等待数据存⼊缓存区发送HAL_UART_Transmit(&huart3,msg_buff, len_u4,100); //将串⼝4接收到的数据通过串⼝3传出memset(msg_buff, 0, sizeof(msg_buff)); //清空缓存区// 指向接收缓存的头部msg = msg_buff;(&huart4)->pRxBuffPtr = msg;flag = 0;len_u4=0;//每次数据长度清0}HAL_Delay(10);}//==============================/* USER CODE END 3 */} 运⾏结果如下,效果正确 谈谈串⼝RS232跟RS485:这两个串⼝除了逻辑电平不同外,还有传输距离也不同,如果对速度要求不⾼,传输距离要⽐较远的就⽤RS485⽐较好,虽然RS485是个半双⼯,但是抑制共模⼲扰能⼒⽐较强,不过这些只是对于硬件层⾯的,对于软件层⾯来说他们的本质都是串⼝,在STM32Cubemx中,都是只是配置为串⼝,按照串⼝的编程来处理即可。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中断方式下进行串口通讯的正确方法
一般普遍的把串口通讯分为查询方式和中断方式。
查询方式比较容易理解,各种书籍上都介绍的比较清楚。
但中断方式,没有几本书讲得好的,甚至有些例程根本无法实际应用。
问题有:
1,半中断法。
只使用接收中断,不使用发送中断,发送时还是依靠查询中断标志的办法;如下:
ES = 0;//若是接收使用中断方式,某些单片机需要关中断。
但C51不一定需要。
这里只是示例。
SBUF = needsendchar;
While (!TI);
TI = 0;
ES = 1;
这里的问题是:发送数据时需要等待数据发完才能继续其他工作,程序效率降低;发送时需要关中断,影响数据接收。
2,接收中断的处理方法错误。
如下:
中断程序:
void ser() interrupt 4 {
RI = 0;
temp = SBUF; //读走数据,放入缓存(全局的)变量
rx_flag = 1; //设置接收标志
}
主程序:
void main(){
…;//初始化
While (1) {
If (rx_flag ==1){//查询接收标志
rx_flag = 0; //清楚接收标志
x = temp; //从暂存变量读取数据
…;//接收处理
}
…; //其它操作
}
}
这里的问题是:如果串口接收数据的间隔时间小于“接收处理”和“其它操作”所用的时间时,接收数据会丢失一部分。
正确使用中断方式处理串口收发应达到以下目的:
1,完全使用中断控制接收和发送,以达到最快的收发速度。
2,接收和发送互不影响,达到全双工通讯效果。
3,应用程序不发生等待,以达到最高运行效率。
正确的中断发送方法如下:
1,建立一个足够大小的环形发送缓冲区,建立一个信号量(用于指示发送的数据量),建立一个发送标志位(用于指示发送状态)。
2,应用程序将数据写入环形发送缓冲区,查询发送接收标志,若不在发送状态,手动触发中断。
3,产生发送中断时,查询信号量,以判别发送缓冲区内是否有数据;若有,置发送标志位,从缓冲区读取数据发送,累减信号量;若无,清除发送标志位。
C51的例程如下:
//变量定义
#define BUF_SIZE 0x10//环形收发缓冲区长度
//发送参数
char tx_circbuf[BUF_SIZE];//环形发送缓冲区
uint8 tx_sem;//信号量
bool tx_run;//发送标志位
uint8 tx_circin;//进环形缓冲区的位置指示
uint8 tx_circout;//出环形缓冲区的位置指示
//发送初始化程序
void tx_init(void){
//硬件初始化略
//发送参数初始化
tx_sem = 0;
tx_run = False;
tx_circin = 0;
tx_circout = 0;
}
//中断程序
void tx_int(void) interrupt 4 {
if (TI){
TI = 0;
if (tx_sem){
SBUF = tx_circbuf [tx_circout]; // 发送缓冲区中的字符
if (++tx_circout >= BUF_SIZE) tx_circout = 0;
tx_sem--;//累减信号量
tx_run = True;//置发送标志位
}
else tx_run = False;//清除发送标志位
}
}
//发送处理程序,由应用程序调用
//输入:发送数据指针,发送数据长度
void tx_data(char * txbuf,uint8 len){
while (len){
tx_circbuf [tx_circin] = *txbuf++;// 存入数据到发送缓冲区
if (++tx_circin >= BUF_SIZE) tx_circin = 0;
tx_sem++;//累减信号量
len--;
if (tx_run == False)TI=1;//查询发送状态标志。
若发送空闲,触发中断,发送数据的工作由中断程序自动完成。
}
}
正确的中断接收方法如下:
1,建立一个足够大小的环形接收缓冲区,建立一个信号量(用于指示接收的数据量)。
2,发生接收中断时,读出字节放入接收缓冲区,并累加信号量。
3,应用程序查询接收标志,如信号量不为0,则从接收缓冲区读取数据进行处理,累减信号量。
C51的例程如下:
//变量定义
#define BUF_SIZE 0x10//环形收发缓冲区长度
//接收参数
char rx_circbuf[BUF_SIZE];// 环形接收缓冲区
uint8 rx_sem;// 信号量
uint8 rx_circin;//进环形缓冲区的位置指示
uint8 rx_circout;//出环形缓冲区的位置指示
//接收初始化程序
void rx_init(void){
//硬件初始化略
//接收参数初始化
rx_sem = 0;
rx_circin = 0;
rx_circout = 0;
}
//中断程序
void rx_int(void) interrupt 4 {
if (RI){
RI = 0;
rx_circbuf [rx_circin] = SBUF;// 读出字节放入接收缓冲区
if (++rx_circin >= BUF_SIZE) rx_circin = 0;
rx_sem++;//累加信号量
}
}
//接收处理程序,由应用程序调用
//输出:读出数据指针;返回:接收到的数据长度
uint8 rx_data(char * rxbuf){
uint8 i;
i = 0;
while (rx_sem){
*rxbuf++ = rx_circbuf [rx_circout];// 从接收缓冲区读取数据
if (++rx_circout >= BUF_SIZE) rx_circout = 0;
rx_sem--;//累减信号量
i++;
}
return i;
}
上述的收发中断程序在应用中合并在一起,即:
void uart_init(void) interrupt 4 {
if (TI){
TI = 0;
…;
}
if (RI){
RI = 0;
…;
}
}
例程中分开表述,只是为了将流程说得更明白些。
上述例程中,未包含环形收发缓冲区溢出状况的处理,需要时自行添加。
上述例程表明了正确使用中断方式处理串口通讯的思路。
当然程序还可以有其它的写法,特别是环形缓冲区中数据出入的方法和信号量的用法。
如在有操作系统的情况下,上述信号量的使用就可以得到操作系统更好支持。
完全中断方式收发数据总结:
1。
数据的收发操作,完全由中断程序自动进行,可以达到最快的收发速度。
即,接收时中断程序负责把数据放入缓冲区,数据的处理由应用程序另行处理;发送时应用程序直接将数据放入缓冲区,启动发送中断后,发送的工作由中断程序自动完成。
2。
由于发送的工作完全由中断处理,因此,应用程序将数据放入缓冲区后,就可以继续运行其它工作,这种“发了不管”的方式极大地提高程序运行效率。
3。
接收数据时,由中断负责将数据放入缓冲区,再由应用程序处理。
应用程序
轮询及处理的时间长短,不会影响接收,就不会导致数据丢失。
4。
由于应用程序中不出现开关中断的操作,因此,发送和接收互不影响,可以达到全双工收发的效果。