STM32F4XX高效驱动篇1-UART
2014-04-27 13:33
211 查看
之前一直在做驱动方面的整理工作,对驱动的高效性有一些自己的理解这里和大家分享一下。并奉驱动程序,本程序覆盖uart1-8。
串口驱动,这是在每个单片机中可以说是必备接口。可以说大部分产品中都会使用,更有甚者一个产品中用到8个串口。这样一个高效的驱动是决定您产品优劣的关键因素。本文主要针对STM32F4XX系列芯片做的一个驱动接口层。以减少您在开发项目时驱动方面所花费时间,以及为程序达到高效的处理为目的。
从51,pic到现在的STM32,个人感觉STM32这方面做的非常突出,丰富的使用模式,强大的引脚映射功能,强大的处理能力等,给我留下的深刻的印象。
关于串口的使用方式,个人总结出以下三种:
1) 中断接收,状态查询发送:这种方式在单片机时代用的比较多,那时候大部分芯片的处理速度不够快,工业控制接口中大部分使用的是9600波特率,程序简单也就对串口发送数据所用时间要求不高。
2) 中断接收,中断发送:这种方式一般会在对高效性要求较高,或软件实时性高的产品中使用。这种方式的好外在于完全释放了CPU在发送开始到结束这一时间CPU控制权。
3) 中断接口,DMA发送:这种方式的使用场合和模式2相同,效率也相差不多。但这种方式确实比模式2CPU的占用时间会更少。
举个例子来说明以上三种模式。假如要把一堆物品从A点运到B点通过传送带,在这个传送过程中传送带上一次只能运一个物品,模式一:把物品放到传送带A点上,然后等待物品由A点被传到B点,这时再放一个物品到传送带上,以此往复所有物品传送过去。模式二:把物品放到A点的传送带上然后就去忙别的事情,看到物品快被传到B点,马上回来再放一个物品到传送带上。很明显这种方式比模式一多了很多空余时间。模式三:这种模式就牛了,在把物品放到A点之前,直接去找了一个“闲杂人等”过来,把物品交给他由他去发,我们需要再发送时,先问下她是否以发完,如果发完了就把新的物品交给他,如果没发完就等一小回再来找他。哈哈,这样咱们就有更多的时间去忙更多的事情了,也不用一回跑来一回跑去。把跑路的时间给节约出来了。
以上三种模式,很明显得出那种模式发送数据效率最高。我们下面说提供的程序就是使用模式三。
说完发送,再说说接收方式。大家一定发现数据接收都是采用中断方式,是的 本人使用过DMA方式进行过多次测试,在使用方面确实没有中断接收灵活。主要有以下两种情况,1,DMA接收数据的主要判断依据1是接收器满中断,这种情况在实际中很少用,除非您的数据是定长。这种方式同时还会存在一些安全隐患,假如噪声原因多接收到一个字节,那之后数据时序就会错位。2,DMA总线空闲中断,这种方式除非是半双工情况下使用。在全双工时被受到发送完成总线空闲的干扰。所以在数据接收方式上主要使用中断。
在数据接收中断方面还分二种方式,
方式1:顺序接收,在接收到第一个数据时就触发超时定时器,每接收到一个字节时就清一次定时器,都到一组数据接收完毕,定时器会因为触发超时中断。在超时中断中来判断一组数据被接收。这种方式一般会用到实时性的一些协议中,比如MODBUS。
方式2:队列接收,申请一个缓冲区收尾相接,接收到数据时载入队列之中,用户只要定时的去队列中读数据,来使用这些数据。这种方式是window,linux的驱动主要接收方式。他的优点就在于在使用数据时无需关闭中断。也就不用怛心在处理上一组数据时了来新的数据会破坏上组数据内容。在方式1中需要考虑在处理数据时暂时性的关下中断。
以下程序则主要是使用到接收使用方式2,发送数据使用模式3的DMA发送,本驱动程序为可裁切,覆盖串口1-8,通过宏裁切。下面提供了一些接口,这里对接口做一个大概的说明。
打开串口
void BSP_UartOpen(uint8_t COM, uint32_t baud, uint8_t data, uint8_t stop, uint8_t parity);
关闭串口
void BSP_UartClose(uint8_t COM);
向串口中写数据
uint32_t BSP_UartWrite(uint8_t COM, uint8_t *buffter, uint32_t len);
从串口中读数据
uint32_t BSP_UartRead(uint8_t COM, uint8_t *buffter, uint32_t len);
查询串口发送忙碌状态
uint32_t BSP_UartTxIdleState(uint8_t COM);
这个接口主要用在,向串口写数据后,在进行下一次写数据之前需要进行查询。
具体接口的使用方法,函数都有详细的说明。
Queue.h
串口驱动,这是在每个单片机中可以说是必备接口。可以说大部分产品中都会使用,更有甚者一个产品中用到8个串口。这样一个高效的驱动是决定您产品优劣的关键因素。本文主要针对STM32F4XX系列芯片做的一个驱动接口层。以减少您在开发项目时驱动方面所花费时间,以及为程序达到高效的处理为目的。
从51,pic到现在的STM32,个人感觉STM32这方面做的非常突出,丰富的使用模式,强大的引脚映射功能,强大的处理能力等,给我留下的深刻的印象。
关于串口的使用方式,个人总结出以下三种:
1) 中断接收,状态查询发送:这种方式在单片机时代用的比较多,那时候大部分芯片的处理速度不够快,工业控制接口中大部分使用的是9600波特率,程序简单也就对串口发送数据所用时间要求不高。
2) 中断接收,中断发送:这种方式一般会在对高效性要求较高,或软件实时性高的产品中使用。这种方式的好外在于完全释放了CPU在发送开始到结束这一时间CPU控制权。
3) 中断接口,DMA发送:这种方式的使用场合和模式2相同,效率也相差不多。但这种方式确实比模式2CPU的占用时间会更少。
举个例子来说明以上三种模式。假如要把一堆物品从A点运到B点通过传送带,在这个传送过程中传送带上一次只能运一个物品,模式一:把物品放到传送带A点上,然后等待物品由A点被传到B点,这时再放一个物品到传送带上,以此往复所有物品传送过去。模式二:把物品放到A点的传送带上然后就去忙别的事情,看到物品快被传到B点,马上回来再放一个物品到传送带上。很明显这种方式比模式一多了很多空余时间。模式三:这种模式就牛了,在把物品放到A点之前,直接去找了一个“闲杂人等”过来,把物品交给他由他去发,我们需要再发送时,先问下她是否以发完,如果发完了就把新的物品交给他,如果没发完就等一小回再来找他。哈哈,这样咱们就有更多的时间去忙更多的事情了,也不用一回跑来一回跑去。把跑路的时间给节约出来了。
以上三种模式,很明显得出那种模式发送数据效率最高。我们下面说提供的程序就是使用模式三。
说完发送,再说说接收方式。大家一定发现数据接收都是采用中断方式,是的 本人使用过DMA方式进行过多次测试,在使用方面确实没有中断接收灵活。主要有以下两种情况,1,DMA接收数据的主要判断依据1是接收器满中断,这种情况在实际中很少用,除非您的数据是定长。这种方式同时还会存在一些安全隐患,假如噪声原因多接收到一个字节,那之后数据时序就会错位。2,DMA总线空闲中断,这种方式除非是半双工情况下使用。在全双工时被受到发送完成总线空闲的干扰。所以在数据接收方式上主要使用中断。
在数据接收中断方面还分二种方式,
方式1:顺序接收,在接收到第一个数据时就触发超时定时器,每接收到一个字节时就清一次定时器,都到一组数据接收完毕,定时器会因为触发超时中断。在超时中断中来判断一组数据被接收。这种方式一般会用到实时性的一些协议中,比如MODBUS。
方式2:队列接收,申请一个缓冲区收尾相接,接收到数据时载入队列之中,用户只要定时的去队列中读数据,来使用这些数据。这种方式是window,linux的驱动主要接收方式。他的优点就在于在使用数据时无需关闭中断。也就不用怛心在处理上一组数据时了来新的数据会破坏上组数据内容。在方式1中需要考虑在处理数据时暂时性的关下中断。
以下程序则主要是使用到接收使用方式2,发送数据使用模式3的DMA发送,本驱动程序为可裁切,覆盖串口1-8,通过宏裁切。下面提供了一些接口,这里对接口做一个大概的说明。
打开串口
void BSP_UartOpen(uint8_t COM, uint32_t baud, uint8_t data, uint8_t stop, uint8_t parity);
关闭串口
void BSP_UartClose(uint8_t COM);
向串口中写数据
uint32_t BSP_UartWrite(uint8_t COM, uint8_t *buffter, uint32_t len);
从串口中读数据
uint32_t BSP_UartRead(uint8_t COM, uint8_t *buffter, uint32_t len);
查询串口发送忙碌状态
uint32_t BSP_UartTxIdleState(uint8_t COM);
这个接口主要用在,向串口写数据后,在进行下一次写数据之前需要进行查询。
具体接口的使用方法,函数都有详细的说明。
1 /* 2 ******************************************************************************** 3 * 4 * Queue.h 5 * 6 * File : Queue.h 7 * Version : V1.0 8 * Author : whq 9 * Mode : Thumb2 10 * Toolchain : 11 * Description : 队列操作头文件 12 * 13 * History : 14 * Date : 2013.07.22 15 *******************************************************************************/ 16 17 18 #ifndef _QUEUE_H_ 19 #define _QUEUE_H_ 20 21 #ifdef __cplusplus 22 extern "C" 23 { 24 #endif 25 26 27 28 #include "stdint.h" 29 30 #define DEBUG_FULL_ASSERT 0 31 32 #ifdef DEBUG_FULL_ASSERT 33 #define ASSERT_PARAM(a) ((a) ? (void)0 : ASSERT_FAILED((uint8_t *)__FILE__, __LINE__)) 34 void ASSERT_FAILED(uint8_t* file, uint32_t line); 35 #else 36 #define ASSERT_PARAM(a) if (a == NULL) return 0; 37 #endif 38 39 40 41 42 43 typedef struct { 44 volatile uint32_t bufSize; 45 volatile uint8_t *pStart; 46 volatile uint8_t *pEnd; 47 volatile uint8_t *pBuf; 48 }QUEUE8_TYPE; 49 50 51 52 53 uint32_t QUEUE_PacketCreate(QUEUE8_TYPE *pQ8, uint8_t *pBuf, uint32_t bufSize); 54 uint32_t QUEUE_PacketIn(QUEUE8_TYPE *pQ8, uint8_t *pData, uint32_t len); 55 uint32_t QUEUE_PacketOut(QUEUE8_TYPE *pQ8, uint8_t *pData, uint32_t dataLen); 56 uint32_t QUEUE_PacketSplit(QUEUE8_TYPE *pQ8, uint8_t startChar, uint8_t endChar, uint8_t *pData, uint32_t dataLen); 57 uint32_t QUEUE_PacketDoubleByteSplit(QUEUE8_TYPE *pQ8, uint8_t splitChar, uint8_t *pData, uint32_t dataLen); 58 uint32_t QUEUE_PacketCharSplit(QUEUE8_TYPE *pQ8, uint8_t splitChar, uint8_t *pData, uint32_t dataLen); 59 uint32_t QUEUE_PacketDoubleCharSplit(QUEUE8_TYPE *pQ8, uint8_t splitChar1, uint8_t splitChar2, uint8_t *pData, uint32_t dataLen); 60 61 62 #ifdef __cplusplus 63 } 64 #endif 65 66 #endif
Queue.h
相关文章推荐
- STM32F4XX串口高效驱动篇1-UART
- STM32F4XX高效驱动篇2 I2C
- STM32F4XX高效驱动篇2 I2C
- STM32F4XX I2C驱动
- STM32F4 开发笔记5: miniUART的使用方法
- 以shader驱动的次世代3d引擎高效光影效果的解决方案
- Linux tty驱动学习 - UART驱动的write操作流程
- 以shader驱动的次世代3d引擎高效光影效果的解决方案
- s3c6140 UART驱动设计
- mega328p-ADC,PWM,UART驱动
- 事件驱动实现单线程实现并发 真正的高效并发
- stm32f4xx系统总线架构
- linux UART 驱动学习笔记——用户如何操作硬件
- usb 转 uart cp210x 驱动解析
- select、poll、epoll的比较-select轮询+sleep,epoll异步事件驱动高效
- 《Linux内核修炼之道》 之 高效学习Linux驱动开发
- linux设备模型之uart驱动架构分析
- tty初探—uart驱动框架分析(二)uart_add_one_port
- Hiwork 高效沟通,一切从话题驱动开始
- ARM9 mini2451裸机学习——UART驱动学习和整理