STM32实现USART+DMA接收未知长度的数据和发送

2019-12-19 18:06发布

STM32学习笔记三 竹天笑
前言:开始学USART+DMA的时候看到帖子《STM32 UART DMA实现未知数据长度接收》,觉得方法妙极了。此下出自此帖子——(整体的思路是这样的,一开始设置好DMA接收,可以把缓冲区长度设置为帧最大长度,我们可以把RX连接到定时器的管脚输入端,并且一开始设置输入并且使能引脚下降沿中断,当帧的第一个字节发送时,因为起始位为低电平,空闲时UART为高电平,满足条件,进入中断,禁止中断,并且在中断中开启定时器,该定时器工作在复位模式,上升沿复位,并且设置好定时器输出比较值为超时时间,比如20ms,这样,在传输后面字节时,肯定会有高低电平出现,即便是传输的是0x00,0xFF,虽然UART数据区不变,但是都为1,或都为0,但是因为起始位为低电平,停止位是高电平,所以肯定会有上升沿,定时器会一直复位,输出定时器的计数器一直到达不了输出比较值,当一帧传输结束后,定时在最后一个字节复位后,由于没有数据继续到达,无法复位,则计数器就能计到输出比较值,这时发出中断,在定时器中断中可以计算出接收数据的长度,并且通知外部数据已经接收完毕。)

今天我在工作中调通了另一种USART+DMA接收未知数据长度的接收,使用的是USRAT空闲总线中断接收,这种方法也在网站上比较多见,以前没试过,今天才知道如此的爽,另外我使用DMA发送USART数据替代了以前的查询法发送,发现更加爽了。其速度快了很多,尤其是在大量数据传输与发送的时候其优势更加明显。
我举个例子:1、后台数据->USART1-> USART2->其它设备,其它设备数据->USART2-> USART1->后台,这两个数据过程也可能同时进行。
2、由于硬件的限制,USART1和USART2的传输波特率不一样,比如USART1使用GPRS通信,USART2使用短距离无线通信;或者USART1使用以太网通信,USART2使用485总线通信。
由于在寝室只有笔记本电脑,只有一个串口转USB,没办法实现两个串口之间的数据转发了,只好实现串口各自的数据转发。
现在我把我实现的过程简单描述一下:
1、        初始化设置:USART1_RX+DMA1_ Channel5,USART2_RX+DMA1_ Channel6,USART1_TX+DMA1_ Channel4,USART2_TX+DMA1_ Channel7(具体设置请看程序包)。
2、        当数据发送给USART1接收完毕时候会引起USART1的串口总线中断,计算DMA1_ Channel5内存数组剩余容量,得到接收的字符长度。将接收的字符复制给DMA1_ Channel4内存数组,启动DMA1_ Channel4通道传输数据,(传输完成需要关闭。)下一次数据接收可以在启动DMA1_ Channel4时候就开始,不需要等待DMA1_ Channel4数据传输完成。但是上一次DMA1_ Channel4完成之前,不可以将数据复制给DMA1_ Channel4内存数组,会冲掉以前数据。
3、        USART2类同USART1。
呵呵,下面贴程序:
  1. IO口定义:
  2. void GPIO_Configuration(void)
  3. {
  4.           GPIO_InitTypeDef GPIO_InitStructure;
  5.           /* 第1步:打开GPIO和USART部件的时钟 */
  6.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  7.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  8.           /* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
  9.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  10.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  11.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.           GPIO_Init(GPIOA, &GPIO_InitStructure);
  13.           /* 第3步:将USART Rx的GPIO配置为浮空输入模式
  14.           由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
  15.           但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
  16.           */
  17.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  18.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  19.           GPIO_Init(GPIOA, &GPIO_InitStructure);
  20.         /* 第1步:打开GPIO和USART2部件的时钟 */
  21.         //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  22.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  23.         /* 第2步:将USART2 Tx的GPIO配置为推挽复用模式 */
  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  27.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  28.         /* 第3步:将USART2 Rx的GPIO配置为浮空输入模式
  29.                 由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
  30.                 但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
  31.         */
  32.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  33.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  34.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  35.         /*  第3步已经做了,因此这步可以不做
  36.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  37.         */
  38.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  39. }
  40. 串口初始化:
  41. void USART_Configuration(void)
  42. {
  43.         USART_InitTypeDef USART_InitStructure;
  44.           /* 第4步:配置USART参数
  45.           - BaudRate = 115200 baud
  46.           - Word Length = 8 Bits
  47.           - One Stop Bit
  48.           - No parity
  49.           - Hardware flow control disabled (RTS and CTS signals)
  50.           - Receive and transmit enabled
  51.           */
  52.           USART_InitStructure.USART_BaudRate = 19200;
  53.           USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  54.           USART_InitStructure.USART_StopBits = USART_StopBits_1;
  55.           USART_InitStructure.USART_Parity = USART_Parity_No;
  56.           USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  57.           USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  58.           USART_Init(USART1, &USART_InitStructure);
  59.           //空闲中断
  60.           USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);
  61.         /* 第5步:使能 USART, 配置完毕 */
  62.           USART_Cmd(USART1, ENABLE);  
  63.         /* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
  64.           如下语句解决第1个字节无法正确发送出去的问题 */
  65.           USART_ClearFlag(USART1, USART_FLAG_TC); /* 清发送外城标志,Transmission Complete flag */
  66.         USART_InitStructure.USART_BaudRate = 9600;
  67.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  68.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  69.         USART_InitStructure.USART_Parity = USART_Parity_No;
  70.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  71.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  72.           USART_Init(USART2, &USART_InitStructure);
  73.           USART_ITConfig(USART2, USART_IT_IDLE , ENABLE);//开启空闲,帧错,噪声,校验错中断
  74.         USART_Cmd(USART2, ENABLE);
  75.         /* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
  76.           如下语句解决第1个字节无法正确发送出去的问题 */
  77.           USART_ClearFlag(USART2, USART_FLAG_TC); /* 清发送外城标志,Transmission Complete flag */
  78. }
  79. DMA配置:
  80. void DMA_Configuration(void)
  81. {
  82.   DMA_InitTypeDef DMA_InitStructure;
  83.   /* DMA clock enable */
  84.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA1
  85.   /* DMA1 Channel4 (triggered by USART1 Tx event) Config */
  86.   DMA_DeInit(DMA1_Channel4);  
  87.   DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
  88.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_SEND_DATA;
  89.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  90.   DMA_InitStructure.DMA_BufferSize = 512;
  91.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  92.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  93.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  94.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  95.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  96.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  97.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  98.   DMA_Init(DMA1_Channel4, &DMA_InitStructure);
  99.   DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
  100.   DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);
  101.   /* Enable USART1 DMA TX request */
  102.   USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
  103.   DMA_Cmd(DMA1_Channel4, DISABLE);
  104.   /* DMA1 Channel5 (triggered by USART2 Tx event) Config */
  105.   DMA_DeInit(DMA1_Channel7);  
  106.   DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
  107.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_SEND_DATA;
  108.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  109.   DMA_InitStructure.DMA_BufferSize = 512;
  110.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  111.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  112.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  113.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  114.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  115.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  116.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  117.   DMA_Init(DMA1_Channel7, &DMA_InitStructure);
  118.   DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);
  119.   DMA_ITConfig(DMA1_Channel7, DMA_IT_TE, ENABLE);
  120.   /* Enable USART1 DMA TX request */
  121.   USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
  122.   DMA_Cmd(DMA1_Channel7, DISABLE);
  123.   /* DMA1 Channel5 (triggered by USART1 Rx event) Config */
  124.   DMA_DeInit(DMA1_Channel5);  
  125.   DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
  126.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RECEIVE_DATA;
  127.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  128.   DMA_InitStructure.DMA_BufferSize = 512;
  129.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  130.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  131.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  132.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  133.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  134.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  135.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  136.   DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  137.   DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
  138.   DMA_ITConfig(DMA1_Channel5, DMA_IT_TE, ENABLE);
  139.   
  140.   /* Enable USART1 DMA RX request */
  141.   USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
  142.   DMA_Cmd(DMA1_Channel5, ENABLE);
  143.   /* DMA1 Channel6 (triggered by USART1 Rx event) Config */
  144.   DMA_DeInit(DMA1_Channel6);  
  145.   DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
  146.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_RECEIVE_DATA;
  147.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  148.   DMA_InitStructure.DMA_BufferSize = 512;
  149.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  150.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  151.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  152.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  153.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  154.   DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
  155.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  156.   DMA_Init(DMA1_Channel6, &DMA_InitStructure);
  157.   DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
  158.   DMA_ITConfig(DMA1_Channel6, DMA_IT_TE, ENABLE);
  159.   /* Enable USART2 DMA RX request */
  160.   USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
  161.   DMA_Cmd(DMA1_Channel6, ENABLE);
  162. }
  163. 中断优先级配置:
  164. void NVIC_Configuration(void)
  165. {
  166.   NVIC_InitTypeDef NVIC_InitStructure;
  167.   /* Configure one bit for preemption priority */
  168.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  
  169.   /* Enable the USART1 Interrupt */
  170.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  171.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  172.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  173.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  174.   NVIC_Init(&NVIC_InitStructure);
  175.   /* Enable the USART2 Interrupt */
  176.   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  177.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  178.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  179.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  180.   NVIC_Init(&NVIC_InitStructure);
  181.   //Enable DMA Channel4 Interrupt
  182.   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
  183.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  184.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  185.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  186.   NVIC_Init(&NVIC_InitStructure);
  187.   //Enable DMA Channel7 Interrupt
  188.   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
  189.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  190.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  191.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  192.   NVIC_Init(&NVIC_InitStructure);
  193.   /*Enable DMA Channel5 Interrupt */
  194.   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
  195.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  196.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  197.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  198.   NVIC_Init(&NVIC_InitStructure);
  199.   /*Enable DMA Channel6 Interrupt */
  200.   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
  201.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  202.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  203.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  204.   NVIC_Init(&NVIC_InitStructure);
  205. }
  206. 数组定义,含义如题名:
  207. u8 USART1_SEND_DATA[512];     
  208. u8 USART2_SEND_DATA[512];
  209. u8 USART1_RECEIVE_DATA[512];
  210. u8 USART2_RECEIVE_DATA[512];
  211. u8 USART1_TX_Finish=1;// USART1发送完成标志量
  212. u8 USART2_TX_Finish=1; // USART2发送完成标志量
  213. USART1中断服务函数
  214. void USART1_IRQHandler(void)
  215. {
  216.         u16 DATA_LEN;
  217.         u16 i;
  218.         if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//如果为空闲总线中断
  219.     {
  220.                 DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据
  221.                 //USART_RX_STA = USART1->SR;//先读SR,然后读DR才能清除
  222.         //USART_RX_STA = USART1->DR;
  223.                   DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel5);
  224.                 if(DATA_LEN > 0)
  225.         {                       
  226.                         while(USART1_TX_Finish==0)//等待数据传输完成才下一次
  227.             {
  228.                 ;
  229.             }
  230.                         //将数据送DMA存储地址
  231.             for(i=0;i<DATA_LEN;i++)
  232.             {
  233.                 USART1_SEND_DATA[i]=USART1_RECEIVE_DATA[i];
  234.             }
  235.             //USART用DMA传输替代查询方式发送,克服被高优先级中断而产生丢帧现象。
  236.             DMA_Cmd(DMA1_Channel4, DISABLE); //改变datasize前先要禁止通道工作
  237.             DMA1_Channel4->CNDTR=DATA_LEN; //DMA1,传输数据量
  238.             USART1_TX_Finish=0;//DMA传输开始标志量
  239.             DMA_Cmd(DMA1_Channel4, ENABLE);                       
  240.                 }
  241.                 //DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据
  242.                 DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清标志
  243.                 DMA1_Channel5->CNDTR = 512;//重装填
  244.                 DMA_Cmd(DMA1_Channel5, ENABLE);//处理完,重开DMA
  245.                 //读SR后读DR清除Idle
  246.                 i = USART1->SR;
  247.                 i = USART1->DR;
  248.         }
  249.         if(USART_GetITStatus(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错
  250.         {
  251.                 USART_ClearITPendingBit(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE);
  252.         }
  253.           USART_ClearITPendingBit(USART1, USART_IT_TC);
  254.           USART_ClearITPendingBit(USART1, USART_IT_IDLE);
  255. }
  256. USART2中断服务函数
  257. void USART2_IRQHandler(void)
  258. {
  259.         u16 DATA_LEN;
  260.         u16 i;
  261.         if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //如果为空闲总线中断
  262.     {
  263.                 DMA_Cmd(DMA1_Channel6, DISABLE);//关闭DMA,防止处理其间有数据
  264.                 //USART_RX_STA = USART1->SR;//先读SR,然后读DR才能清除
  265.         //USART_RX_STA = USART1->DR;
  266.                   DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel6);
  267.                 if(DATA_LEN > 0)
  268.         {                       
  269.                         while(USART2_TX_Finish==0)//等待数据完成才下一次
  270.             {
  271.                 ;
  272.             }
  273.                         //将数据送DMA存储地址
  274.             for(i=0;i<DATA_LEN;i++)
  275.             {
  276.                 USART2_SEND_DATA[i]=USART2_RECEIVE_DATA[i];
  277.             }
  278.             //USART用DMA传输替代查询方式发送,克服被高优先级中断而产生丢帧现象。
  279.             DMA_Cmd(DMA1_Channel7, DISABLE); //改变datasize前先要禁止通道工作
  280.             DMA1_Channel7->CNDTR=DATA_LEN; //DMA1,传输数据量
  281.             USART2_TX_Finish=0;//DMA传输开始标志量
  282.             DMA_Cmd(DMA1_Channel7, ENABLE);                       
  283.                 }
  284.                 //DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据
  285.                 DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);//清标志
  286.                 DMA1_Channel6->CNDTR = 512;//重装填
  287.                 DMA_Cmd(DMA1_Channel6, ENABLE);//处理完,重开DMA
  288.                 //读SR后读DR清除Idle
  289.                 i = USART2->SR;
  290.                 i = USART2->DR;
  291.         }
  292.         if(USART_GetITStatus(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错
  293.         {
  294.                 USART_ClearITPendingBit(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE);
  295.         }
  296.           USART_ClearITPendingBit(USART2, USART_IT_TC);
  297.           USART_ClearITPendingBit(USART2, USART_IT_IDLE);
  298. }
  299. DMA1_Channel5中断服务函数
  300. void DMA1_Channel5_IRQHandler(void)
  301. {
  302.   DMA_ClearITPendingBit(DMA1_IT_TC5);
  303.   DMA_ClearITPendingBit(DMA1_IT_TE5);
  304.   DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据
  305.   DMA1_Channel5->CNDTR = 580;//重装填
  306.   DMA_Cmd(DMA1_Channel5, ENABLE);//处理完,重开DMA
  307. }
  308. DMA1_Channel6中断服务函数
  309. void DMA1_Channel6_IRQHandler(void)
  310. {
  311.   DMA_ClearITPendingBit(DMA1_IT_TC6);
  312.   DMA_ClearITPendingBit(DMA1_IT_TE6);
  313.   DMA_Cmd(DMA1_Channel6, DISABLE);//关闭DMA,防止处理其间有数据
  314.   DMA1_Channel6->CNDTR = 580;//重装填
  315.   DMA_Cmd(DMA1_Channel6, ENABLE);//处理完,重开DMA
  316. }
  317. DMA1_Channel4中断服务函数
  318. //USART1使用DMA发数据中断服务程序
  319. void DMA1_Channel4_IRQHandler(void)
  320. {
  321.   DMA_ClearITPendingBit(DMA1_IT_TC4);
  322.   DMA_ClearITPendingBit(DMA1_IT_TE4);
  323.   DMA_Cmd(DMA1_Channel4, DISABLE);//关闭DMA
  324.   USART1_TX_Finish=1;//置DMA传输完成
  325. }
  326. DMA1_Channel7中断服务函数
  327. //USART2使用DMA发数据中断服务程序
  328. void DMA1_Channel7_IRQHandler(void)
  329. {
  330.   DMA_ClearITPendingBit(DMA1_IT_TC7);
  331.   DMA_ClearITPendingBit(DMA1_IT_TE7);
  332.   DMA_Cmd(DMA1_Channel7, DISABLE);//关闭DMA
  333.   USART2_TX_Finish=1;//置DMA传输完成
  334. }
复制代码呵呵,全部完,但是程序在开始启动时会出现自己发几个不知道什么字符,之后一切正常。如有什么问题,请大神指教。个人认为问题不大,因为在工作的时候通过STM32访问后台或者后台访问STM32大量的间隔密的数据时没有出现问题。而如果没有使用DMA,单帧数据发收可以,多帧数据经过USART1转USART2,就收不到从USART2反馈的第二帧数据了。不一定是速度上的问题,可能是我处理顺序的问题,但是不管是巧合,还是瞎撞的,总归解决办法的就是好办法。
工程下载地址:http://115.com/file/dpj82l3j#
USART_DMA_Interrupt.rar
说明文档下载地址:http://115.com/file/dpj8i8ov#
STM32实现USART+DMA接收未知长度的数据和发送.doc
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
98条回答
Achin
2019-12-26 19:18
nazily215 发表于 2012-9-12 13:52
粗略看了一下你代碼,有幾點建議一下:
1)你的ISR竟然使用WHILE(1)循環?不妨拖到main函數裏執行?這 ...

首先非常谢谢前辈的指点。

但我又提出如下几点疑问:

回复4、关于你说的半双工状态,mcu收到数据肯定要处理了,处理数据的话,没收完,能处理吗?(程序中的转发过程等效于实际的处理过程)
回复1、有了回复4这个理由,当然需要判断处理完成没有,因此有了你说的那个while(1),等待数据处理完成。
回复2、3,呵呵,就是你说的这样,但是我也不知道如何处理了。数据一直不断的来,我又需要不断的取出来,取数据的过程还在进数据,只有取的不够快(我这明显慢一些,要出问题),取的肯定是不准的。这个时候空闲总线检测已经失效,那如果实际真那么密集的数据量,那就不能用空闲总线了,还不如就用接收中断,然后用个计数器(或者阁下所说的定时器),取数据即可。

一周热门 更多>