午睡之前,版主上传了串口通讯之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);
}
}
工程文件:
我要赚赏金
