第八节 串口学习之中断输入输出
本节主要讲了 使用 中断的方式 进行串口数据的发送与接收。
pdf版学习笔记如下:
8科星F107开发板学习笔记—串口学习之中断输入输出.pdf
(190.49 KB)
源码工程文件
8科星F107开发板学习笔记源码—串口学习之中断输入输出.rar
(3.18 MB)
部分内容如下:
中断是在任务稍多的项目中经常使用的一种程序运行方式,他在一定程度上保障了程序的实时性。这里我们介绍一下串口的中断发送和接收。 串口的中断接收,首先我们应该想到的是:我们怎么知道数据接收完了呢? 一般情况下有两种方式: 1、规定带有帧结束标志的数据,比如一些串口功能器件发来的数据 我们应如何判断一个完整的数据 以便后续的分析呢,我们拿gps模块为例,gps的数据的个数是不断变化的,因为很多参数的数据是不固定的,怎样才能一帧一帧的接收分析呢?经常用的就是判断数据的开始和结束标志。 2、根据帧间隔时间。 很多数据采集设备发来的数据都是隔一段时间传输一次 这样的数据我们就可以根据字节间的时间间隔来判断一帧的结束,比如一个连续的数据帧的字节间隔是固定的,这个时间由波特率决定,比如时间算出来是T1 那么我们就可以认为在大于1.5倍 T1间隔没有新数据收到就认为一帧的接收结束。
我们的工程测试程序是根据第2种来实现串口的中断接收,这里因为是测试程序,所以帧判断的tim时间设为1s,也就是说只要你发送的数据间隔小于1s 我们都认为是一帧的数据。
首先,这里需要添加外设库文件stm32f10x_usart.c和stm32f10x_tim.c,文件的路径为“\Libraries\STM32F10x_StdPeriph_Driver\src”。
完整的main.c文件代码如下,所有的配置代码都在这个文件下面 /* Includes------------------------------------------------------------------*/ #include "stm32f10x.h"
u8Uart_send_counter; //Uart_send()函数发送的字节数 vu8*Uart_send_pointer;//发送的数组指针
/* Privatevariables ---------------------------------------------------------*/ USART_InitTypeDefUSART_InitStructure;
/* Privatefunction prototypes -----------------------------------------------*/
voidGPIO_Configuration(void); voidNVIC_Configuration(void); voidTIM2_Configuration(void);
/* Privatefunctions ---------------------------------------------------------*/
/** * @param None * @retval None */ int main(void) { /* System Clocks Configuration */ SystemInit(); TIM2_Configuration(); /* NVIC configuration */ NVIC_Configuration();
/* Configure the GPIO ports */ GPIO_Configuration();
/* USARTy andUSARTz configuration ------------------------------------------------------*/ /* 9600 8 n 1 */ USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength =USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_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;
/* Configure USARTy */ USART_Init(USART1, &USART_InitStructure); /* Configure USARTz */
/* Enable USARTy Receive and Transmitinterrupts */ USART_ITConfig(USART1, USART_IT_RXNE,ENABLE); // USART_ITConfig(USART1, USART_IT_TXE,ENABLE);//使能中断这里先不使能 在后面中断发送之前发送 USART_Cmd(USART1, ENABLE);
while (1) { } }
voidGPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/* Configure USARTx_Tx as alternate functionpush-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USARTx_Rx as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } /******************************************************************* * FunctionName : Uart_InterruptsendY 带字节传输 *Description : 中断发送字符串 * Input : 参数一:uart1 2 3 4.。 参数二:要发送的字符串地址指针 参数三:要传输的字节数 * Output : 无 * Return : 无 *******************************************************************************/ voidUart_InterruptsendY(USART_TypeDef *USARTx,vu8* Uart0_sended,u8 NbOfBytes ) { Uart_send_counter=NbOfBytes; Uart_send_pointer=Uart0_sended; USART_SendData(USARTx,*Uart_send_pointer++); USART_ITConfig(USARTx, USART_IT_TXE,ENABLE); //UART_ITConfig(UARTx,UART_IT_TxEmpty,ENABLE); }
voidTIM2_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
// TIM2 Configuration:向上计数中断: /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 7200-1; TIM_TimeBaseStructure.TIM_Prescaler =10000-1;// TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); TIM_ITConfig(TIM2, TIM_IT_Update , ENABLE);//开启计数中断 /* TIM2 enable counter */ //TIM_Cmd(TIM2, ENABLE);//开启时钟 这里不开启 在接受到数据时开启 来判断是不是帧结束 } /** * @brief Configures the nested vectored interrupt controller. * @param None * @retval None */ voidNVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption PriorityBits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* Enable the USARTy Interrupt */ NVIC_InitStructure.NVIC_IRQChannel =USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; NVIC_Init(&NVIC_InitStructure); }
定时器中断和串口中断处理函数都在stm32f10x_it.c文件下面,代码如下: void TIM2_IRQHandler(void) {/******处理完数据后一定要把Uart0_rev_count清零, 但是为了安全一开始就请零可能更好,这样的话 我们规定用Uart0_rev_countmap来代替Uart0_rev_count******************** u32 Uart0_rev_countmap; /***清楚tim中断和关闭tim中断,在uart接受中断里 有相应的使能****/ TIM_Cmd(TIM2, DISABLE); TIM_ClearITPendingBit(TIM2,TIM_IT_Update); /****copy Uart0_rev_count的值****/ Uart0_rev_countmap=RxCounter1; RxCounter1=0; /*****测试语句 返回接受的语句 顺便测试中断发送 这里以后是数据处理函数***********************/ Uart_InterruptsendY(USART1,RxBuffer1,Uart0_rev_countmap); }
void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET) { TIM_Cmd(TIM2, ENABLE); TIM2->CNT &=0x0000;//定时器延时设置 每次接受清零 当接受间隔超过定时器定的值时 进入tim中断 认为一帧接受完成 RxBuffer1[RxCounter1++] =USART_ReceiveData(USART1); USART_ClearITPendingBit(USART1, USART_IT_RXNE); } if(USART_GetITStatus(USART1,USART_IT_TXE) != RESET) { Uart_send_counter--; if(Uart_send_counter>0) { USART_SendData(USART1,*Uart_send_pointer++); } else USART_ITConfig(USART1,USART_IT_TXE, DISABLE); } }
|