STM32 是一款基于ARM Cortex-M3内核的32位MCU,主频最高可达72M。最近因为要在车机上集成TPMS功能, 便开始着手STM32的开发工作,STM32F10x系列共有5个串口(USART1~USART5),支持DMA方式通信,DMA方式由于不需要CPU的参与,而是直接由DMA控制器完成串口数据的读写,因而可以很大程度的提高CPU的利用率。在使用STM32串口之前需要做一系列的初始化工作:

1.RCC(复位和时钟控制寄存器)初始化,启用GPIO、DMA、USART时钟。

2.NVIC(嵌套向量中断控制寄存器)初始化,完成各个硬件中断的配置。

3.USART初始话,配置串口,设置DMA通道等。

4.DMA初始化,完成DMA的配置。

最后是使能USART和DMA。下面是通过DMA的方式从串口USART1接收数据,STM32工作后串口数据由DMA控制器接收存到指定buffer,读取数据直接从DMA buffer中读取即可。发送数据采用非DMA方式,首先将待发送的数据存入到发送队列,然后在任务循环中将队列中的数据发送给USART1。实例代码如下:

 //**********************************************************************************************
// STM32F10x USART Test
// compiler: Keil UV3
// 2011-03-28 , By friehood
//**********************************************************************************************
static int8u rDMABuffer[]; // DMA buffer
static int16u rDMARear = sizeof(rDMABuffer); static int8u USART_RevBuf[]; // 串口接收buffer
static int8u USART_SndBuf[]; // 串口发送buffer
static int8u Head=,Tail=; // 发送buffer的头尾 // 串口任务
void Task_USART(void)
{
int16u end;
if (USART1->SR & (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE))
{
USART_ReceiveData(USART1);
} // DMA接收
end = DMA_GetCurrDataCounter(DMA1_Channel5);
/*if((sizeof(rDMABuffer)-end)>0)
dbgprt("DMA available datalen=%d/n",sizeof(rDMABuffer)-end); */
while(rDMARear != end)
{
USART_receive(rDMABuffer[sizeof(rDMABuffer)-rDMARear]);
if (!(--rDMARear))
{
rDMARear = sizeof(rDMABuffer);
}
} //发送
if(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET)
{
int8u chr;
// 从发送队列取出一个字符
if(PopFront(&chr))
{
USART_SendData(USART1, chr);
dbgprt("USART_SendData:0x%02x/n",chr);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{
}
}
}
} // USART串口初始化
void dev_USART_init(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure; /* DMA1 Channel5 (triggered by USART1 Rx event) Config */ //参见 STM32 datasheet
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)rDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(rDMABuffer);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure); USART_InitStructure.USART_BaudRate = ;
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; //配置IO: GPIOA9和GPIOA10分别作为串口TX、RX端。 见STM32 datasheet
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIO_InitStructure); /* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART1 DMA Rxrequest */
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
/* Enable DMA1 Channel5 */
DMA_Cmd(DMA1_Channel5, ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
} // 向串口发送数据
void USART_send(const int8u *pBuf, int8u len)
{
int i;
if(pBuf == NULL)
{
return;
}
// 将数据压入到发送队列
dbgprt("USART_PushBack:");
for(i=;i<len;i++)
{
PushBack(*pBuf);
dbgprt("0x%02x ",*pBuf);
pBuf++;
}
dbgprt("/n");
} // 向发送队列尾部插入一个字节
void PushBack(int8u byte)
{
USART_SndBuf[Tail++]= byte;
if(Tail >= ARRAYSIZE(USART_SndBuf))
Tail = ;
if(Tail == Head)
Head = Tail+;
} // 从发送队列头部取出一个字节
bool PopFront(int8u *byte)
{
if(Head >= ARRAYSIZE(USART_SndBuf))
Head = ;
if(Head == Tail)
return FALSE;
*byte = USART_SndBuf[Head++];
return TRUE;
} // 处理接收到的串口数据
void USART_receive(int8u byte)
{
// Treate received data
// Place Code here
// ...
} // CRC校验
bool CheckCRC(const int8u *str, int8u len, const int8u *crcstr)
{
int8u checkSum;
if(str == NULL || crcstr== NULL)
return FALSE;
GetCRC(str,len,&checkSum);
if(checkSum != *crcstr)
return FALSE;
else
return TRUE;
} // 获取CRC
bool GetCRC(const int8u *str, int8u len, int8u *crcstr)
{
int8u i;
int8u checkSum;
if(str == NULL || crcstr== NULL)
return FALSE;
checkSum = *str;
for(i=; i<len; i++)
{
checkSum ^= *(str+i);
}
*crcstr = checkSum;
return TRUE;
}

STM32 串口DMA方式接收(转)的更多相关文章

  1. STM32串口DMA超时接收方法,可大大节约CPU时间

    //超时时间定义#define        UART1_TimeoutComp 2  //20ms#define        UART2_TimeoutComp 10  //100ms#defin ...

  2. STM32串口DMA接收数据错位——暴力解决方法

    背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...

  3. STM32串口——中断方式的一般配置方法

    #include "stm32f10x.h" /************************************************ 该程序讲解串口程序的一般配置方法: ...

  4. STM32 ~ 串口DMA通道查找

    STM32F4XX: /**************************************************************************************** ...

  5. STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率

    前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...

  6. RT-Thread中的串口DMA分析

    这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考. 背景 在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的 ...

  7. STM32 SPI DMA 的使用

    一是想总结一下SPI总线的特点与注意点,二是总结一下SPI DMA的使用 一.SPI信号线说明 通常SPI通过4个引脚与外部器件相连: MISO:主设备输入/从设备输出引脚.该引脚在从模式下发送数据, ...

  8. STM32 HAL库利用DMA实现串口不定长度接收方法

    参考:https://blog.csdn.net/u014470361/article/details/79206352 我这里使用的芯片是 F1 系列的,主要是利用 DMA 数据传输方式实现的,在配 ...

  9. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

随机推荐

  1. Atmel Studio 6.0 重新安装

    问题描述:        Atmel Studio 6.0 重新安装     在卸载Atmel Studio6.0之后,重新安装Atmel Studio6.0软件,提示cannot find one ...

  2. 团体程序设计天梯赛-练习集L1-010. 比较大小

    L1-010. 比较大小 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 杨起帆(浙江大学城市学院) 本题要求将输入的任意3个整数从小 ...

  3. 如何保护 .NET 应用的安全?

    自从 Web 应用能给访问者提供丰富的内容之后,黑客们就把目光转向任何他们能够破坏,损毁,欺骗的漏洞.通过网络浏览器提供的应用越来越多,网络罪犯们可以利用的漏洞数量也呈指数增长起来. 大多数企业都依赖 ...

  4. codeforces #305 D Mike and Fish

    正解貌似是大暴搜? 首先我们考虑这是一个二分图,建立网络流模型后很容易得出一个算法 S->行 容量为Num[X]/2; 行->列 容量为1 且要求(x,y)这个点存在 列->T 容量 ...

  5. Android:布局合集

    本文归纳Android布局中所用到的知识点,网络上的教程说得太细化,而对于前端来说,下面的归纳最适合不过了. Android五大布局: LinearLayout 线性布局 Relativelayout ...

  6. 面试大总结:Java搞定面试中的链表题目总结

    package LinkedListSummary; import java.util.HashMap; import java.util.Stack; /** * http://blog.csdn. ...

  7. Django用户认证系统(二)Web请求中的认证

    在每个Web请求中都提供一个 request.user 属性来表示当前用户.如果当前用户未登录,则该属性为AnonymousUser的一个实例,反之,则是一个User实例. 你可以通过is_authe ...

  8. linux下关于程序性能和系统性能的工具、方法

    观察性能/状态的方法:top free netstat /pro/目录下的信息 其中/pro/meminfo下的信息相当丰富 ------------------------------------- ...

  9. UVA 10041 Vito's Family (中位数)

      Problem C: Vito's family  Background The world-known gangster Vito Deadstone is moving to New York ...

  10. 【剑指offer】找出数组中出现一次的两个数

    2013-09-08 10:50:46 一个整型数组中,除了两个数字之外,其他数字都出现了2次,找出这两个只出现一次的数字,要求时间复杂度是O(N),空间复杂度是O(1). 小结: 任何数与0异或,结 ...