午睡之前,版主上传了串口通讯之Uart_Int中断程序。我们知道在51单片机时代的项目设计中,在串口用于通讯使用,而通讯使用时为了避免数据丢失的现象,我们都会采用接收中断的方式,而发送采用查询的方式,但在强大的Cortex-M3系统下面,有了DMA这个功能。具体DMA的原理及用途版主这里不再给大家引用文献,请自行百度之。版主只给大家带来一个典型应用实例:发送使用DMA方式,而接收由于未知数据长度,因此,本例中仍然采用中断方式。不是我编程速度快,而是GD32F130与ST的兼容性做的较好,分分钟就搞定了~~
实验内容:
通过板载的按键,每当按下按键时,都会向串口发送一段字符串“hello EEPW”,而每接收一个字节的数据都会更新LED灯的闪烁频率。
实验现象:
由于采用了按键扫描状态机的机制,发送没有出现连发与丢失现象。LED灯的闪烁频率也随着发送的数据变化而变化。
[图片貌似与上一个没有区别,但版主的确是重新截图的~~]
实验结论:
实验结果与设计方案完全相符,STM32F0xx的固件库目前完美支持GD32F130C8芯片。
源代码:
uint16_t gCntLed[2]; uint16_t gKeyCnt; uint8_t gKeyStatus; int8_t gSendBuf[256]; int8_t gRcvBuf[256]; uint16_t TxIndex; uint16_t RxIndex; uint16_t gSendCnt; uint8_t gSendCmdStatus; /** * @} */ /** @defgroup blink_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup blink_Private_Functions * @{ */ /** * @brief key check * @param * @retval * @date 2015-03-28 * @note */ void KeyCheck(void) { bool KeyStatus; KeyStatus = KeyScan(0); switch(gKeyStatus) { case 0: /*!< 空闲状态 */ { if(KeyStatus == true) { gKeyStatus = 1; } else { gKeyStatus = 0; LedOff(0); gSendCmdStatus = 0; } break; } case 1: /*!< 消抖状态 */ { if(KeyStatus == true) { gKeyCnt = 5; gKeyStatus = 2; } else { gKeyCnt = 0; gKeyStatus = 0; } break; } case 2: /*!< 按下状态 */ { if(KeyStatus == true) { if(gKeyCnt == 0) { //按键按下执行内容 LedOn(0); gSendCmdStatus |= 0x0F; } else { gKeyStatus = 2; } } else { gKeyCnt = 0; gKeyStatus = 0; } break; } case 3: /*!< 确认按下 */ { LedOn(0); break; } default: gKeyStatus = 0; } } /** * @brief uart_int * @param * @retval * @date 2015-03-29 * @note 发送使用DMA方式,接收使用中断 */ void UartConfig(uint32_t band) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* Connect pin to Periph */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); /* Configure pins as AF pushpull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = band; 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(USART1, &USART_InitStructure); /* NVIC configuration */ /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_TDR_ADDRESS; DMA_InitStructure.DMA_BufferSize = (uint16_t)256; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&gSendBuf[0]); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_Init(DMA1_Channel2, &DMA_InitStructure); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); USART_Cmd(USART1, ENABLE); } void main(void) { uint16_t i; int8_t Str[] = "hello EEPW\r\n"; gKeyStatus = 0; bspInit(); gCntLed[0] = 500; gCntLed[1] = 500; TxIndex = 0; gSendCnt = 12; for(i = 0; i < gSendCnt; i++) { gSendBuf[i] = Str[i]; } UartConfig(115200); if (SysTick_Config(48000)) //参数为系统时钟的向上溢出值,此配置为48000,即1ms中断一次 { /* Capture error */ while (1); } while(1) { if(gCntLed[1] == 0) { LedToggle(1); gCntLed[1] = gRcvBuf[0] * 4; } KeyCheck(); if(gSendCmdStatus > 0) { if(gSendCmdStatus < 0x10) { // for(i = 0; i < gSendCnt; i++) // { // USART_SendData(USART1, gSendBuf[i]); // /* Loop until transmit data register is empty */ // while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) // {;}; // } DMA_Cmd(DMA1_Channel2, DISABLE); DMA_SetCurrDataCounter(DMA1_Channel2, gSendCnt); DMA_Cmd(DMA1_Channel2, ENABLE); gSendCmdStatus |= 0xF0; } } } } /** * @brief SysTick_Handler的中断入口函数 * @param * @retval * @date 2014-11-23 * @note */ void SysTick_Handler(void) { if(gCntLed[0] > 0) { gCntLed[0]--; } else { gCntLed[0] = 0; } if(gCntLed[1] > 0) { gCntLed[1]--; } else { gCntLed[1] = 0; } if(gKeyCnt > 0) { gKeyCnt--; } else { gKeyCnt = 0; } } /** * @brief USART1_Handler的中断入口函数 * @param * @retval * @date 2015-03-29 * @note */ void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) { gRcvBuf[0] = USART_ReceiveData(USART1); } }
工程文件: