Chinaunix首页 | 论坛 | 博客
  • 博客访问: 47012
  • 博文数量: 9
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 110
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 12:19
文章分类

全部博文(9)

文章存档

2017年(4)

2016年(5)

我的朋友

分类: 嵌入式

2016-11-04 09:07:22


点击(此处)折叠或打开

  1. #ifndef __USART_H
  2. #define __USART_H

  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif

  6. #include "stdio.h"
  7. #include "stm32f4xx.h"


  8. #define USART2_DMA_TX_BUF_SIZE        256
  9. #define USART1_DMA_TX_BUF_SIZE        256
  10. #define USART1_DMA_RX_BUF_SIZE        256

  11. // 用户缓存容量定义最好不能小于USART1 RX缓存容量,
  12. // 否则可能在一次接收大量数据时用户缓存溢出
  13. #define USART_USER_Q_BUF_SIZE        ((USART1_DMA_RX_BUF_SIZE) << 1)



  14. #define _DEBUG
  15. #if defined(_DEBUG) || defined(DEBUG)
  16. #define logx(...)                { usart2_printf(__VA_ARGS__); }
  17. #else
  18. #define logx(...)
  19. #endif


  20. uint16_t usart1_user_rx_buf_pop(uint8_t* data, uint16_t len);
  21. uint8_t usart1_user_rx_buf_is_full(void);
  22. uint8_t usart1_user_rx_buf_is_empty(void);
  23. uint16_t usart1_user_rx_buf_get_avail(void);

  24. void usart2_dma_init(void);
  25. void usart1_dma_init(void);

  26. void usart1_dma_tx(uint8_t* data, uint16_t size);
  27. void usart2_dma_tx(uint8_t* data, uint16_t size);
  28. int usart1_printf(const char *format, ...);
  29. int usart2_printf(const char *format, ...);


  30. #ifdef __cplusplus
  31. }
  32. #endif

  33. #endif


点击(此处)折叠或打开

  1. #include <stdarg.h>
  2. #include <string.h>
  3. #include "delay.h"
  4. #include "usart-dma.h"


  5. // USART1 TX/RX 缓存定义
  6. static __align(8) uint8_t usart1_dma_tx_buf[USART1_DMA_TX_BUF_SIZE];
  7. static __align(8) uint8_t usart1_dma_rx_buf[USART1_DMA_RX_BUF_SIZE];
  8. static volatile uint8_t flag_tx_usart1_dma_busy = 0;

  9. // USART2 TX 缓存定义
  10. static __align(8) uint8_t usart2_dma_tx_buf[USART2_DMA_TX_BUF_SIZE];
  11. static volatile uint8_t flag_tx_usart2_dma_busy = 0;


  12. // 用户缓存定义,USART1 RX数据中转到该缓存供用户读取
  13. #define USER_Q_STATUS_AVAIL        0
  14. #define USER_Q_STATUS_FULL        1
  15. #define USER_Q_STATUS_EMPTY        2
  16. typedef struct {
  17.     uint8_t buff[USART_USER_Q_BUF_SIZE];
  18.     volatile uint16_t head;
  19.     volatile uint16_t tail;
  20.     volatile uint8_t status;
  21. } usart_user_q_t;

  22. static usart_user_q_t usart1_user_q = {{0}, 0, 0, USER_Q_STATUS_EMPTY};



  23. #if 1
  24. #pragma import(__use_no_semihosting)
  25. struct __FILE {
  26.     int handle;
  27. } __stdout;

  28. void _sys_exit(int x) { x = x; }    // 定义_sys_exit()以避免使用半主机模式

  29. int sendchar( char c )
  30. {
  31.     while ( (USART2->SR & 0x80) == 0 ); // 80 = TXE, 40 = TC
  32.     USART2->DR = c;
  33.     return 1;
  34. }

  35. /*int getkey(void)
  36. {
  37.     while ( (USART2->SR & 0x20) == 0 ); // 20 = RXNE
  38.     return (USART2->DR);
  39. }*/

  40. int fputc( int ch, FILE *f )
  41. {
  42.     if ( (char)ch == '\n' ) sendchar('\r');
  43.     return sendchar((char)ch);
  44. }

  45. // 由于USART2没有实现接收数据功能,故不重定义fgetc函数
  46. //int fgetc( FILE *f ) { return getkey(); }

  47. int ferror( FILE *f )
  48. {
  49.     // Your implementation of ferror
  50.     return EOF;
  51. }

  52. void _ttywrch( int ch )
  53. {
  54.     if ( (char)ch == '\n' ) sendchar('\r');
  55.     sendchar((char)ch);
  56. }
  57. #endif



  58. //////////////////////////////////////////////////////////////////////////
  59. ////////////////////////////// USART1-DMA RX FIFO操作 /////////////////////

  60. /*********************************************************************
  61. * 内部函数:    读取USART1数据,
  62. *            USART1及对应的DMA中断调用本函数,往用户缓存中填充数据。
  63. * data:        源缓存,即分配给DMA2_Stream2的缓存
  64. * len:        读取数据大小,按字节计,不应该超过data容量
  65. * 返回值:    返回实际读取到的字节数据个数,如果为零,表示USART1内部缓存为空
  66. **********************************************************************/
  67. static uint16_t usart1_user_rx_buf_push( uint8_t* data, uint16_t len )
  68. {
  69.     uint16_t avail, avail0;
  70.     uint16_t head = usart1_user_q.head;        // tail为push指针,head为pop指针
  71.     uint16_t tail = usart1_user_q.tail;
  72.     uint8_t* pqbuff = usart1_user_q.buff;

  73.     // 首先检测缓存是否为满,满则直接返回
  74.     if ( USER_Q_STATUS_FULL == usart1_user_q.status )
  75.         return 0;

  76.     if ( tail >= head )        // 可能需要分两段push
  77.     {
  78.         avail0 = USART_USER_Q_BUF_SIZE - tail;
  79.         avail = avail0 + head;
  80.         if ( len > avail ) len = avail;

  81.         if ( len > avail0 ) {
  82.             memcpy(pqbuff+tail, data, avail0);
  83.             memcpy(pqbuff, data+avail0, len-avail0);
  84.         }
  85.         else
  86.             memcpy(pqbuff+tail, data, len);
  87.     }
  88.     else    // 缓存部分可用
  89.     {
  90.         avail = head - tail;
  91.         if ( len > avail ) len = avail;
  92.         memcpy(pqbuff+tail, data, len);
  93.     }

  94.     // 最后更改状态及tail值
  95.     usart1_user_q.status = (avail > len) ? USER_Q_STATUS_AVAIL : USER_Q_STATUS_FULL;
  96.     usart1_user_q.tail = (tail+len) % USART_USER_Q_BUF_SIZE;
  97.     return len;
  98. }

  99. /*********************************************************************
  100. * 接口函数:    读取USART1数据
  101. * data:        目的缓存
  102. * len:        读取数据大小,按字节计,不应该超过data容量
  103. * 返回值:    返回实际读取到的字节数据个数,如果为零,表示USART1内部缓存为空
  104. **********************************************************************/
  105. uint16_t usart1_user_rx_buf_pop( uint8_t* data, uint16_t len )
  106. {
  107.     uint16_t avail, avail0;
  108.     uint16_t head = usart1_user_q.head;        // tail为push指针,head为pop指针
  109.     uint16_t tail = usart1_user_q.tail;
  110.     uint8_t* pqbuff = usart1_user_q.buff;

  111.     // 首先检测缓存是否为空,空则直接返回
  112.     if ( USER_Q_STATUS_EMPTY == usart1_user_q.status )
  113.         return 0;

  114.     if ( head >= tail )    // 可能需要分两段pop
  115.     {
  116.         avail0 = USART_USER_Q_BUF_SIZE - head;
  117.         avail = avail0 + tail;
  118.         if ( len > avail ) len = avail;

  119.         if ( len > avail0 ) {
  120.             memcpy(data, pqbuff+head, avail0);
  121.             memcpy(data+avail0, pqbuff, tail);
  122.         }
  123.         else
  124.             memcpy(data, pqbuff+head, len);
  125.     }
  126.     else {
  127.         avail = tail - head;
  128.         if ( len > avail ) len = avail;
  129.         memcpy(data, pqbuff+head, len);
  130.     }

  131.     // 最后更改状态及head值
  132.     usart1_user_q.status = (avail > len) ? USER_Q_STATUS_AVAIL : USER_Q_STATUS_EMPTY;
  133.     usart1_user_q.head = (head+len) % USART_USER_Q_BUF_SIZE;
  134.     return len;
  135. }

  136. /*********************************************************************
  137. * USART1 RX缓存是否满。满返回非零,不满返回零。
  138. **********************************************************************/
  139. uint8_t usart1_user_rx_buf_is_full(void)
  140. {
  141.     if ( USER_Q_STATUS_FULL == usart1_user_q.status )
  142.         return 1;
  143.     return 0;
  144. }

  145. /*********************************************************************
  146. * USART1 RX缓存是否空。空返回非零,不空返回零。
  147. **********************************************************************/
  148. uint8_t usart1_user_rx_buf_is_empty(void)
  149. {
  150.     if ( USER_Q_STATUS_EMPTY == usart1_user_q.status )
  151.         return 1;
  152.     return 0;
  153. }

  154. /*********************************************************************
  155. * 获取USART1 RX缓存中可读取的数据字节个数
  156. **********************************************************************/
  157. uint16_t usart1_user_rx_buf_get_avail(void)
  158. {
  159.     uint8_t status = usart1_user_q.status;
  160.     uint16_t head = usart1_user_q.head;        // tail为push指针,head为pop指针
  161.     uint16_t avail, tail = usart1_user_q.tail;

  162.     if ( USER_Q_STATUS_EMPTY == status ) return 0;
  163.     if ( USER_Q_STATUS_FULL == status ) return (USART_USER_Q_BUF_SIZE);

  164.     if ( head >= tail ) avail = USART_USER_Q_BUF_SIZE - head + tail;
  165.     else avail = tail - head;
  166.     return avail;
  167. }






  168. //////////////////////////////////////////////////////////////////////////
  169. /////////////////// USART1 及 USART2 初始化 ///////////////////////////////
  170. /*
  171. * http://blog.csdn.net/jdh99/article/details/43307121
  172. * http://jmarple.com/transmitting-data-over-usart-using-dma/    (需要翻墙)
  173. */

  174. static void imp_usart2_dma_init()
  175. {
  176.     GPIO_InitTypeDef GPIO_InitStructure;
  177.     USART_InitTypeDef USART_InitStructure;
  178.     DMA_InitTypeDef DMA_InitStructure;
  179.     NVIC_InitTypeDef NVIC_InitStructure;

  180.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  181.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  182.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

  183.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
  184.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

  185.     GPIO_InitStructure.GPIO_Pin                = GPIO_Pin_2 | GPIO_Pin_3;
  186.     GPIO_InitStructure.GPIO_Mode            = GPIO_Mode_AF;
  187.     GPIO_InitStructure.GPIO_Speed            = GPIO_Speed_50MHz;
  188.     GPIO_InitStructure.GPIO_OType            = GPIO_OType_PP;
  189.     GPIO_InitStructure.GPIO_PuPd            = GPIO_PuPd_UP;
  190.     GPIO_Init(GPIOA, &GPIO_InitStructure);


  191.     //////////////////////////////////////////////////////////////////////////
  192.     // USART2配置

  193.     USART_InitStructure.USART_BaudRate        = 115200;
  194.     USART_InitStructure.USART_WordLength    = USART_WordLength_8b;
  195.     USART_InitStructure.USART_StopBits        = USART_StopBits_1;
  196.     USART_InitStructure.USART_Parity        = USART_Parity_No;
  197.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  198.     USART_InitStructure.USART_Mode            = USART_Mode_Rx | USART_Mode_Tx;
  199.     USART_Init(USART2, &USART_InitStructure);

  200.     USART_Cmd(USART2, ENABLE);
  201.     USART_ClearFlag(USART2, USART_FLAG_TC);


  202.     //////////////////////////////////////////////////////////////////////////
  203.     // DMA TX配置

  204.     // DMA中断配置
  205.     NVIC_InitStructure.NVIC_IRQChannel                        = DMA1_Stream6_IRQn;
  206.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 3;
  207.     NVIC_InitStructure.NVIC_IRQChannelSubPriority            = 3;
  208.     NVIC_InitStructure.NVIC_IRQChannelCmd                    = ENABLE;
  209.     NVIC_Init(&NVIC_InitStructure);

  210.     // DMA通道配置
  211.     DMA_DeInit(DMA1_Stream6);
  212.     DMA_InitStructure.DMA_Channel                = DMA_Channel_4;
  213.     DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)(&USART2->DR);        // 外设地址
  214.     DMA_InitStructure.DMA_Memory0BaseAddr        = (uint32_t)usart2_dma_tx_buf;    // 内存地址
  215.     DMA_InitStructure.DMA_DIR                    = DMA_DIR_MemoryToPeripheral;    // DMA传输方向
  216.     DMA_InitStructure.DMA_BufferSize            = USART2_DMA_TX_BUF_SIZE;        // 设置DMA在传输时缓冲区的长度
  217.     DMA_InitStructure.DMA_PeripheralInc            = DMA_PeripheralInc_Disable;    // 设置DMA的外设递增模式,一个外设
  218.     DMA_InitStructure.DMA_MemoryInc                = DMA_MemoryInc_Enable;            // 设置DMA的内存递增模式
  219.     DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_Byte;    // 外设数据字长
  220.     DMA_InitStructure.DMA_MemoryDataSize        = DMA_PeripheralDataSize_Byte;    // 内存数据字长
  221.     DMA_InitStructure.DMA_Mode                    = DMA_Mode_Normal;                // 设置DMA的传输模式
  222.     DMA_InitStructure.DMA_Priority                = DMA_Priority_High;            // 设置DMA的优先级别
  223.     DMA_InitStructure.DMA_FIFOMode                = DMA_FIFOMode_Disable;            // 指定如果FIFO模式或直接模式将用于指定的流:不使能FIFO模式
  224.     DMA_InitStructure.DMA_FIFOThreshold            = DMA_FIFOThreshold_HalfFull;    // 指定了FIFO阈值水平
  225.     DMA_InitStructure.DMA_MemoryBurst            = DMA_MemoryBurst_Single;        // 指定的Burst转移配置内存传输
  226.     DMA_InitStructure.DMA_PeripheralBurst        = DMA_PeripheralBurst_Single;    // 指定的Burst转移配置外围转移
  227.     DMA_Init(DMA1_Stream6, &DMA_InitStructure);
  228.     DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, ENABLE);    // 使能传输完成中断

  229.     USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);    // 采用DMA方式发送
  230. }


  231. static void imp_uart1_dma_init(void)
  232. {
  233.     NVIC_InitTypeDef NVIC_InitStructure;        // 定义中断结构体
  234.     GPIO_InitTypeDef GPIO_InitStructure;        // 定义IO初始化结构体
  235.     USART_InitTypeDef USART_InitStructure;        // 定义串口结构体
  236.     DMA_InitTypeDef DMA_InitStructure;            // 定义DMA结构体

  237.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  238.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);    // 使能USART1时钟
  239.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);    // 启动DMA时钟


  240.     //////////////////////////////////////////////////////////////////////////
  241.     // 串口TX DMA 配置

  242.     // DMA发送中断设置
  243.     NVIC_InitStructure.NVIC_IRQChannel                        = DMA2_Stream7_IRQn;
  244.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 3;
  245.     NVIC_InitStructure.NVIC_IRQChannelSubPriority            = 3;
  246.     NVIC_InitStructure.NVIC_IRQChannelCmd                    = ENABLE;
  247.     NVIC_Init(&NVIC_InitStructure);

  248.     // DMA通道配置
  249.     DMA_DeInit(DMA2_Stream7);
  250.     DMA_InitStructure.DMA_Channel                = DMA_Channel_4;                
  251.     DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)(&USART1->DR);        // 外设地址
  252.     DMA_InitStructure.DMA_Memory0BaseAddr        = (uint32_t)usart1_dma_tx_buf;    // 内存地址
  253.     DMA_InitStructure.DMA_DIR                    = DMA_DIR_MemoryToPeripheral;    // DMA传输方向
  254.     DMA_InitStructure.DMA_BufferSize            = USART1_DMA_TX_BUF_SIZE;        // 设置DMA在传输时缓冲区的长度
  255.     DMA_InitStructure.DMA_PeripheralInc            = DMA_PeripheralInc_Disable;    // 设置DMA的外设递增模式,一个外设
  256.     DMA_InitStructure.DMA_MemoryInc                = DMA_MemoryInc_Enable;            // 设置DMA的内存递增模式
  257.     DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_Byte;    // 外设数据字长
  258.     DMA_InitStructure.DMA_MemoryDataSize        = DMA_PeripheralDataSize_Byte;    // 内存数据字长
  259.     DMA_InitStructure.DMA_Mode                    = DMA_Mode_Normal;                // 设置DMA的传输模式
  260.     DMA_InitStructure.DMA_Priority                = DMA_Priority_High;            // 设置DMA的优先级别
  261.     DMA_InitStructure.DMA_FIFOMode                = DMA_FIFOMode_Disable;            // 指定如果FIFO模式或直接模式将用于指定的流:不使能FIFO模式
  262.     DMA_InitStructure.DMA_FIFOThreshold            = DMA_FIFOThreshold_HalfFull;    // 指定了FIFO阈值水平
  263.     DMA_InitStructure.DMA_MemoryBurst            = DMA_MemoryBurst_Single;        // 指定的Burst转移配置内存传输
  264.     DMA_InitStructure.DMA_PeripheralBurst        = DMA_PeripheralBurst_Single;    // 指定的Burst转移配置外围转移
  265.     DMA_Init(DMA2_Stream7, &DMA_InitStructure);        // 配置DMA1的通道
  266.     DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);    // 使能传输完成中断


  267.     //////////////////////////////////////////////////////////////////////////
  268.     // 串口RX DMA 配置

  269.     // DMA接收中断设置
  270.     NVIC_InitStructure.NVIC_IRQChannel                        = DMA2_Stream2_IRQn;
  271.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 3;
  272.     NVIC_InitStructure.NVIC_IRQChannelSubPriority            = 3;
  273.     NVIC_InitStructure.NVIC_IRQChannelCmd                    = ENABLE;
  274.     NVIC_Init(&NVIC_InitStructure);

  275.     // DMA通道配置
  276.     DMA_DeInit(DMA2_Stream2);
  277.     DMA_InitStructure.DMA_Channel                = DMA_Channel_4;
  278.     DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)(&USART1->DR);        // 外设地址
  279.     DMA_InitStructure.DMA_Memory0BaseAddr        = (uint32_t)usart1_dma_rx_buf;    // 内存地址
  280.     DMA_InitStructure.DMA_DIR                    = DMA_DIR_PeripheralToMemory;    // dma传输方向
  281.     DMA_InitStructure.DMA_BufferSize            = USART1_DMA_RX_BUF_SIZE;        // 设置DMA在传输时缓冲区的长度
  282.     DMA_InitStructure.DMA_PeripheralInc            = DMA_PeripheralInc_Disable;    // 设置DMA的外设递增模式,一个外设
  283.     DMA_InitStructure.DMA_MemoryInc                = DMA_MemoryInc_Enable;            // 设置DMA的内存递增模式
  284.     DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_Byte;    // 外设数据字长
  285.     DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_Byte;        // 内存数据字长
  286.     DMA_InitStructure.DMA_Mode                    = DMA_Mode_Normal;                // 设置DMA的传输模式
  287.     DMA_InitStructure.DMA_Priority                = DMA_Priority_VeryHigh;        // 设置DMA的优先级别
  288.     DMA_InitStructure.DMA_FIFOMode                = DMA_FIFOMode_Disable;            // 指定如果FIFO模式或直接模式将用于指定的流:不使能FIFO模式
  289.     DMA_InitStructure.DMA_FIFOThreshold            = DMA_FIFOThreshold_Full;        // 指定了FIFO阈值水平,半满为DMA_FIFOThreshold_HalfFull
  290.     DMA_InitStructure.DMA_MemoryBurst            = DMA_MemoryBurst_Single;        // 指定的Burst转移配置内存传输
  291.     DMA_InitStructure.DMA_PeripheralBurst        = DMA_PeripheralBurst_Single;    // 指定的Burst转移配置外围转移
  292.     DMA_Init(DMA2_Stream2, &DMA_InitStructure);        // 配置DMA1的通道
  293.     DMA_ITConfig(DMA2_Stream2, DMA_IT_TC/*DMA_IT_HT*/, ENABLE);    // 使能传输完成中断
  294.     DMA_Cmd(DMA2_Stream2, ENABLE);                    // 使能通道


  295.     //////////////////////////////////////////////////////////////////////////
  296.     // 初始化串口参数
  297.     USART_InitStructure.USART_WordLength            = USART_WordLength_8b;
  298.     USART_InitStructure.USART_StopBits                = USART_StopBits_1;
  299.     USART_InitStructure.USART_Parity                = USART_Parity_No;
  300.     USART_InitStructure.USART_HardwareFlowControl    = USART_HardwareFlowControl_None;
  301.     USART_InitStructure.USART_Mode                    = USART_Mode_Rx | USART_Mode_Tx;
  302.     USART_InitStructure.USART_BaudRate                = 115200;
  303.     USART_Init(USART1, &USART_InitStructure);        // 初始化串口

  304.     // 配置中断
  305.     NVIC_InitStructure.NVIC_IRQChannel                = USART1_IRQn;    // 通道设置为串口中断
  306.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 3;        // 抢占优先级3
  307.     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 3;        // 子优先级3
  308.     NVIC_InitStructure.NVIC_IRQChannelCmd            = ENABLE;        // 打开中断
  309.     NVIC_Init(&NVIC_InitStructure);

  310.     USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);    // 采用DMA方式发送
  311.     USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);    // 采用DMA方式接收

  312.     // 中断配置
  313.     USART_ITConfig(USART1, USART_IT_TC, DISABLE);
  314.     USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
  315.     USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
  316.     USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);

  317.     USART_Cmd(USART1, ENABLE);        // 启动串口


  318.     //////////////////////////////////////////////////////////////////////////
  319.     // GPIO复用

  320.     // 串口1对应引脚复用映射
  321.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);     // GPIOA9复用为USART1
  322.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);     // GPIOA10复用为USART1

  323.     // USART1端口配置
  324.     GPIO_InitStructure.GPIO_Pin        = GPIO_Pin_9 | GPIO_Pin_10; // GPIOA9与GPIOA10
  325.     GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;                // 复用功能
  326.     GPIO_InitStructure.GPIO_Speed    = GPIO_Speed_50MHz;            // 速度50MHz
  327.     GPIO_InitStructure.GPIO_OType    = GPIO_OType_PP;             // 推挽复用输出
  328.     GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;             // 上拉
  329.     GPIO_Init(GPIOA, &GPIO_InitStructure);                         // 初始化PA9,PA10
  330. }





  331. //////////////////////////////////////////////////////////////////////////
  332. /////////////////////////// USART2 中断处理函数 ////////////////////////////

  333. /*********************************************************************
  334. * USART2 DMA 发送中断处理函数
  335. **********************************************************************/
  336. void DMA1_Stream6_IRQHandler(void)
  337. {
  338.     if ( DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) ) {
  339.         DMA_Cmd(DMA1_Stream6, DISABLE);    // 关闭DMA
  340.         DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);    // Clear DMA Stream Transfer Complete interrupt pending bit
  341.         flag_tx_usart2_dma_busy = 0;    // 发送完成
  342.     }
  343. }



  344. //////////////////////////////////////////////////////////////////////////
  345. ////////////////////////// USART1 中断处理函数 /////////////////////////////


  346. /*********************************************************************
  347. * USART1 DMA 发送中断处理函数
  348. **********************************************************************/
  349. void DMA2_Stream7_IRQHandler(void)
  350. {
  351.     if ( DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7) ) {
  352.         DMA_Cmd(DMA2_Stream7, DISABLE);                        // 关闭DMA
  353.         DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);    // Clear DMA Stream Transfer Complete interrupt pending bit
  354.         flag_tx_usart1_dma_busy = 0;                        // 发送完成
  355.     }
  356. }

  357. /*********************************************************************
  358. * USART1 DMA 接收中断处理
  359. * !!!注意:DMA通道禁用->使能过程应该尽可能的快,
  360. *        如需要添加调试用打印输出信息,
  361. *        务必添加在使能DMA之后,且不能过多耗时!!!!
  362. **********************************************************************/
  363. void DMA2_Stream2_IRQHandler(void)
  364. {
  365.     uint16_t len = 0, lenuser = 0;

  366.     if ( DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF2/*DMA_IT_HTIF2*/) )
  367.     {
  368.         DMA_Cmd(DMA2_Stream2, DISABLE);
  369.         /*DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2);
  370.         DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_HTIF2);*/
  371.         DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);

  372.         len = USART1_DMA_RX_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream2);
  373.         lenuser = usart1_user_rx_buf_push(usart1_dma_rx_buf, len);

  374.         DMA_SetCurrDataCounter(DMA2_Stream2, USART1_DMA_RX_BUF_SIZE);    // 数据取出后,重新设置RX缓存大小
  375.         DMA_Cmd(DMA2_Stream2, ENABLE);        // 打开DMA

  376.         //log("usart1 rx dma:%d\n", len);
  377.         if ( lenuser < len ) {
  378.             logx("usart1 dma: overflow<%d, %d>\n", len, lenuser);
  379.         }
  380.     }
  381. }

  382. /*********************************************************************
  383. * USART1 中断处理函数
  384. * !!!注意:DMA通道禁用->使能过程应该尽可能的快,
  385. *        如需要添加调试用打印输出信息,
  386. *        务必添加在使能DMA之后,且不能过多耗时!!!!
  387. **********************************************************************/
  388. void USART1_IRQHandler(void)
  389. {
  390.     uint16_t len = 0, lenuser = 0;

  391.     if( USART_GetITStatus(USART1, USART_IT_IDLE) )
  392.     {
  393.         USART1->SR; USART1->DR; // 清USART_IT_IDLE标志
  394.         USART_ClearITPendingBit(USART1, USART_IT_IDLE);
  395.         //USART_ClearITPendingBit(USART1, USART_IT_TC);

  396.         DMA_Cmd(DMA2_Stream2, DISABLE);                    // 关闭DMA
  397.         DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2);    // 清除DMA满标志位
  398.         DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_HTIF2);    // 清除DMA半满标志位

  399.         // 拷贝出rx缓存中的数据
  400.         len = USART1_DMA_RX_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream2);
  401.         if ( len > 0 ) lenuser = usart1_user_rx_buf_push(usart1_dma_rx_buf, len);

  402.         DMA_SetCurrDataCounter(DMA2_Stream2, USART1_DMA_RX_BUF_SIZE);    // 设置传输数据长度
  403.         DMA_Cmd(DMA2_Stream2, ENABLE);        // 打开DMA

  404.         //log("usart1 idle:%d\n", len);
  405.         if ( lenuser < len && len > 0 ) {
  406.             logx("usart1 idle: overflow<%d, %d>\n", len, lenuser);
  407.         }
  408.     }
  409. }




  410. //////////////////////////////////////////////////////////////////////////
  411. //////////////////////////// 接口函数 /////////////////////////////////////


  412. void usart1_dma_init(void)
  413. {
  414.     usart1_user_q.head = 0;
  415.     usart1_user_q.tail = 0;
  416.     usart1_user_q.status = USER_Q_STATUS_EMPTY;

  417.     flag_tx_usart1_dma_busy = 0;
  418.     imp_uart1_dma_init();
  419. }

  420. void usart2_dma_init(void)
  421. {
  422.     flag_tx_usart2_dma_busy = 0;
  423.     imp_usart2_dma_init();
  424. }

  425. /*********************************************************************
  426. * 接口函数: USART1发送数据
  427. * 参数:    data: 发送数据存放地址
  428. *         size: 发送数据字节数
  429. * 说明: size值不能超过USART1_DMA_TX_LEN,否则剩余数据不会被发送。
  430. **********************************************************************/
  431. void usart1_dma_tx( uint8_t* data, uint16_t size )
  432. {
  433.     while ( flag_tx_usart1_dma_busy );        // 等待空闲
  434.     flag_tx_usart1_dma_busy = 1;

  435.     if ( size > USART1_DMA_TX_BUF_SIZE ) size = USART1_DMA_TX_BUF_SIZE;
  436.     memcpy(usart1_dma_tx_buf, data, size);        // 复制数据
  437.     DMA_SetCurrDataCounter(DMA2_Stream7, size);    // 设置传输数据长度
  438.     DMA_Cmd(DMA2_Stream7, ENABLE);                // 打开DMA,开始发送
  439. }

  440. /*********************************************************************
  441. * 接口函数: USART2发送数据
  442. * 参数:    data: 发送数据存放地址
  443. *         size: 发送数据字节数
  444. * 说明: size值不能超过USART2_DMA_TX_LEN,否则剩余数据不会被发送。
  445. **********************************************************************/
  446. void usart2_dma_tx( uint8_t* data, uint16_t size )
  447. {
  448.     while ( flag_tx_usart2_dma_busy );        // 等待空闲
  449.     flag_tx_usart2_dma_busy = 1;

  450.     if ( size > USART2_DMA_TX_BUF_SIZE ) size = USART2_DMA_TX_BUF_SIZE;
  451.     memcpy(usart2_dma_tx_buf, data, size);        // 复制数据
  452.     DMA_SetCurrDataCounter(DMA1_Stream6, size);    // 设置传输数据长度
  453.     DMA_Cmd(DMA1_Stream6, ENABLE);                // 打开DMA,开始发送
  454. }

  455. /*********************************************************************
  456. * 接口函数: 格式化数据输出到USART1
  457. * 说明: 格式化缓存容量USART1_DMA_TX_LEN,即USART1发送缓存容量。
  458. **********************************************************************/
  459. int usart1_printf( const char* format, ...)
  460. {
  461.     int rv;
  462.     va_list arg;

  463.     while ( flag_tx_usart1_dma_busy );        // 等待空闲
  464.     flag_tx_usart1_dma_busy = 1;

  465.     va_start(arg, format);
  466.     rv = vsnprintf((char*)usart1_dma_tx_buf, USART1_DMA_TX_BUF_SIZE, format, arg);
  467.     va_end(arg);

  468.     DMA_SetCurrDataCounter(DMA2_Stream7, rv);    // 设置传输数据长度
  469.     DMA_Cmd(DMA2_Stream7, ENABLE);                // 打开DMA,开始发送
  470.     return rv;
  471. }

  472. /*********************************************************************
  473. * 接口函数: 格式化数据输出到USART2
  474. * 说明: 格式化缓存容量USART2_DMA_TX_LEN,即USART2发送缓存容量。
  475. **********************************************************************/
  476. int usart2_printf( const char* format, ...)
  477. {
  478.     int rv;
  479.     va_list arg;

  480.     while ( flag_tx_usart2_dma_busy );        // 等待空闲
  481.     flag_tx_usart2_dma_busy = 1;

  482.     va_start(arg, format);
  483.     rv = vsnprintf((char*)usart2_dma_tx_buf, USART2_DMA_TX_BUF_SIZE, format, arg);
  484.     va_end(arg);

  485.     DMA_SetCurrDataCounter(DMA1_Stream6, rv);    // 设置传输数据长度
  486.     DMA_Cmd(DMA1_Stream6, ENABLE);                // 打开DMA,开始发送
  487.     return rv;
  488. }

阅读(5268) | 评论(0) | 转发(0) |
0

上一篇: IO多路复用:select

下一篇:C++技巧: SFINAE

给主人留下些什么吧!~~