1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
(RXNE中断和IDLE中断的区别? 当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。于是我决定在产生RXNE中断时将接收到的一个字节的数据用数组保存起来。在产生IDLE中断的时候,改变ReceivedFlag(自己定义的一个检测帧数据接收完成状态的标志)的状态。 main.c main.c: #include "stm32f10x.h" #include "stdio.h" extern void delay_ms(u16 time); void USART_Config(void); void NVIC_Configuration(void); int fputc(int ch, FILE *f); void Usart_SendByte(); uint16_t i; uint8_t u2_Temp; extern uint8_t u3Temp; extern uint16_t uart_p; int RxFlag; extern uint8_t ReceivedFlag,tempU3,uart3_RXbuff[]; /* * UART2: TX: PA2 RX:PA3 * UART3:TX:PB10 RX:PB11 TXRXEN:PD3 * UART5:TX:PC12 RX:PD1 TXRXEN:PD0 * */ int main() { SystemInit();//72m NVIC_Configuration(); USART_Config(); // printf("重定向成功n"); for(i=0;i<=0xff;i++) { Usart_SendByte( USART2,i); // printf("%d",i); } while(1) { if(ReceivedFlag == 1)//帧数据显示。收到一帧数据时,显示接收中断数组保存的一帧数据 { for(uart_p= 1; uart_p <= u3Temp; uart_p++) { Usart_SendByte(USART2,uart3_RXbuff[uart_p]); } ReceivedFlag = 0; uart_p = 1; } } } static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 配置USART为中断源 */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; /* 抢断优先级*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 初始化配置NVIC */ NVIC_Init(&NVIC_InitStructure); } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 打开串口GPIO的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 打开串口外设的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); // 将USART Tx的GPIO配置为推挽复用模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 将USART Rx的GPIO配置为浮空输入模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置串口的工作参数 // 配置波特率 USART_InitStructure.USART_BaudRate = 115200; // 配置 针数据字长 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; // 完成串口的初始化配置 USART_Init(USART2, &USART_InitStructure); // 串口中断优先级配置 NVIC_Configuration(); // 使能串口空闲中断(用于检测一帧数据接收完毕) USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); // 使能串口接收中断 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(USART2, ENABLE); // 清除发送完成标志 //USART_ClearFlag(USART1, USART_FLAG_TC); } /***************** 发送一个字符 **********************/ void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* 发送一个字节数据到USART */ USART_SendData(pUSARTx,ch); /* 等待发送数据寄存器为空 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } //重定向c库函数printf到串口,重定向后可使用printf函数 int fputc(int ch, FILE *f)//定义此函数需要添加stdio.h文件 { /* 发送一个字节数据到串口 */ USART_SendData(USART2, (uint8_t) ch); /* 等待发送完毕 */ while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); return (ch); } ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 int fgetc(FILE *f) { /* 等待串口输入数据 */ while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(USART2); } stm32f10x_it.c: #define UART_BUFF_SIZE 1024 uint16_t uart_p = 1; uint8_t uart3_RXbuff[UART_BUFF_SIZE]; uint8_t u3Temp; uint8_t tempU3; uint8_t ReceivedFlag = 1; uint16_t clr; void USART2_IRQHandler(void) { if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)//收到一个字节数据 { uart3_RXbuff[uart_p] = USART_ReceiveData(USART2);//保存串口接收到的数据 USART_SendData(USART2,uart3_RXbuff[uart_p]); //将保存的串口接收到的数据在串口调试助手显示(单字节数据显示) uart_p++; } if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //收到一帧的数据 { ReceivedFlag = 1; u3Temp = uart_p-1; clr = USART2->DR;//清除空闲中断标志 clr = USART2->SR; } 接下来附上RS485的收发例程:(其实没啥区别只是485多了一个收发控制引脚,发送数据的时候要记得将控制引脚拉高即置位该引脚,接收数据的时候将引脚拉低即复位该引脚,不多说 见程序吧) main.c: #include "stm32f10x.h" #include "bsp_485.h" uint8_t u2_Temp; extern uint8_t u3Temp; extern uint16_t uart3_p; extern uint16_t ReceivedUsart3Flag,tempU3,uart3_RXbuff[]; char *pbuf; uint16_t len,iU3; void SendUsart3Buff(); void SendU3DatatoDebug(); static void Delay(__IO uint32_t nCount); //简单的延时函数//设置static:解决重复定义 int main(void) { /*初始化USART 配置模式为 115200 8-N-1,中断接收*/ USART_Config(); /* 发送使能 */ RS485_TX_EN() ; SendUsart3Buff(); // Delay(0xFFF); RS485_RX_EN(); while(1) { if(ReceivedUsart3Flag == 1)//接收到一帧数据 { SendU3DatatoDebug(); } } } static void Delay(__IO uint32_t nCount) //简单的延时函数 { for(; nCount != 0; nCount--); } void SendUsart3Buff() { for(iU3=0;iU3<=0xff;iU3++) { Usart_SendByte(USART3,iU3); } } /*Description:调试通信程序专用,用于将接收到的数据再发送到串口调试助手显示 * */ void SendU3DatatoDebug() { for(uart3_p= 1; uart3_p <= u3Temp; uart3_p++) { Usart_SendByte(USART3,uart3_RXbuff[uart3_p]); } uart3_p = 1; RS485_RX_EN(); ReceivedUsart3Flag = 0; } 485.c: #include "bsp_485.h" static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 配置USART为中断源 */ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; /* 抢断优先级*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 初始化配置NVIC */ NVIC_Init(&NVIC_InitStructure); } /** * U3:TX:PB10 RX:PB11 TXRXEN:PD3 * U5:TX:PC12 RX:PD1 TXRXEN:PD0 * */ void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 打开串口GPIO的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//TX、RX是时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);//EN时钟 // 打开串口外设的时钟 DEBUG_USART_APBxClkCmd(RCC_APB1Periph_USART3, ENABLE);//USART时钟 // 将USART Tx的GPIO配置为推挽复用模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 将USART Rx的GPIO配置为浮空输入模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); /* 设置485收发控制管脚为推挽输出Out_PP */ GPIO_InitStructure.GPIO_Pin = RS485_RE_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD , &GPIO_InitStructure); // 配置串口的工作参数 // 配置波特率 USART_InitStructure.USART_BaudRate = 115200; // 配置 针数据字长 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; // 完成串口的初始化配置 USART_Init(USART3, &USART_InitStructure); // 串口中断优先级配置 NVIC_Configuration(); // 使能串口接收中断 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 使能串口空闲中断(用于检测一帧数据接收完毕) USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); // 使能串口 USART_Cmd(USART3, ENABLE); /*控制 485 芯片进入接收模式*/ RS485_RX_EN();// } /***************** 发送一个字符 **********************/ void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* 发送一个字节数据到USART */ USART_SendData(pUSARTx,ch); /* 等待发送数据寄存器为空 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } /***************** 发送字符串 **********************/ void Usart_SendString( USART_TypeDef * pUSARTx, char *str) { unsigned int k=0; do { Usart_SendByte( pUSARTx, *(str + k) ); k++; } while(*(str + k)!=' |