您的位置:首页 > 其它

32 ART DMA 接收未知长度的数据和发送

2014-05-27 10:31 288 查看

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

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。

呵呵,下面贴程序:IO口定义:

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/* 第1步:打开GPIO和USART部件的时钟 */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

/* 第2步:将USART Tx的GPIO配置为推挽复用模式 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 第3步:将USART Rx的GPIO配置为浮空输入模式

由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的

但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数

*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 第1步:打开GPIO和USART2部件的时钟 */

//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

/* 第2步:将USART2 Tx的GPIO配置为推挽复用模式 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 第3步:将USART2 Rx的GPIO配置为浮空输入模式

由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的

但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数

*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/*第3步已经做了,因此这步可以不做

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

*/

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

串口初始化:

void USART_Configuration(void)

{

USART_InitTypeDef USART_InitStructure;

/* 第4步:配置USART参数

- BaudRate = 115200 baud

- Word Length = 8 Bits

- One Stop Bit

- No parity

- Hardware flow control disabled (RTS and CTS signals)

- Receive and transmit enabled

*/

USART_InitStructure.USART_BaudRate = 19200;

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);

//空闲中断

USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);

/* 第5步:使能 USART, 配置完毕 */

USART_Cmd(USART1, ENABLE);

/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去

如下语句解决第1个字节无法正确发送出去的问题 */

USART_ClearFlag(USART1, USART_FLAG_TC); /* 清发送外城标志,Transmission Complete flag */

USART_InitStructure.USART_BaudRate = 9600;

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(USART2, &USART_InitStructure);

USART_ITConfig(USART2, USART_IT_IDLE , ENABLE);//开启空闲,帧错,噪声,校验错中断

USART_Cmd(USART2, ENABLE);

/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去

如下语句解决第1个字节无法正确发送出去的问题 */

USART_ClearFlag(USART2, USART_FLAG_TC); /* 清发送外城标志,Transmission Complete flag */

}

DMA配置:

void DMA_Configuration(void)

{

DMA_InitTypeDef DMA_InitStructure;

/* DMA clock enable */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA1

/* DMA1 Channel4 (triggered by USART1 Tx event) Config */

DMA_DeInit(DMA1_Channel4);

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_SEND_DATA;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 512;

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_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel4, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);

DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);

/* Enable USART1 DMA TX request */

USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);

DMA_Cmd(DMA1_Channel4, DISABLE);

/* DMA1 Channel5 (triggered by USART2 Tx event) Config */

DMA_DeInit(DMA1_Channel7);

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_SEND_DATA;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 512;

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_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel7, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);

DMA_ITConfig(DMA1_Channel7, DMA_IT_TE, ENABLE);

/* Enable USART1 DMA TX request */

USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

DMA_Cmd(DMA1_Channel7, DISABLE);

/* DMA1 Channel5 (triggered by USART1 Rx event) Config */

DMA_DeInit(DMA1_Channel5);

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RECEIVE_DATA;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = 512;

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_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel5, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);

DMA_ITConfig(DMA1_Channel5, DMA_IT_TE, ENABLE);

/* Enable USART1 DMA RX request */

USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);

DMA_Cmd(DMA1_Channel5, ENABLE);

/* DMA1 Channel6 (triggered by USART1 Rx event) Config */

DMA_DeInit(DMA1_Channel6);

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_RECEIVE_DATA;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = 512;

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_Medium;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel6, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);

DMA_ITConfig(DMA1_Channel6, DMA_IT_TE, ENABLE);

/* Enable USART2 DMA RX request */

USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);

DMA_Cmd(DMA1_Channel6, ENABLE);

}

中断优先级配置:

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

/* Configure one bit for preemption priority */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/* Enable the USART1 Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

/* Enable the USART2 Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

//Enable DMA Channel4 Interrupt

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

//Enable DMA Channel7 Interrupt

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

/*Enable DMA Channel5 Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

/*Enable DMA Channel6 Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

数组定义,含义如题名:

u8 USART1_SEND_DATA;

u8 USART2_SEND_DATA;

u8 USART1_RECEIVE_DATA;

u8 USART2_RECEIVE_DATA;

u8 USART1_TX_Finish=1;// USART1发送完成标志量

u8 USART2_TX_Finish=1; // USART2发送完成标志量

USART1中断服务函数

void USART1_IRQHandler(void)

{

u16 DATA_LEN;

u16 i;

if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//如果为空闲总线中断

{

DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据

//USART_RX_STA = USART1->SR;//先读SR,然后读DR才能清除

//USART_RX_STA = USART1->DR;

DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel5);

if(DATA_LEN > 0)

{

while(USART1_TX_Finish==0)//等待数据传输完成才下一次

{

;

}

//将数据送DMA存储地址

for(i=0;i<DATA_LEN;i++)

{

USART1_SEND_DATA=USART1_RECEIVE_DATA;

}

//USART用DMA传输替代查询方式发送,克服被高优先级中断而产生丢帧现象。

DMA_Cmd(DMA1_Channel4, DISABLE); //改变datasize前先要禁止通道工作

DMA1_Channel4->CNDTR=DATA_LEN; //DMA1,传输数据量

USART1_TX_Finish=0;//DMA传输开始标志量

DMA_Cmd(DMA1_Channel4, ENABLE);

}

//DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据

DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清标志

DMA1_Channel5->CNDTR = 512;//重装填

DMA_Cmd(DMA1_Channel5, ENABLE);//处理完,重开DMA

//读SR后读DR清除Idle

i = USART1->SR;

i = USART1->DR;

}

if(USART_GetITStatus(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错

{

USART_ClearITPendingBit(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE);

}

USART_ClearITPendingBit(USART1, USART_IT_TC);

USART_ClearITPendingBit(USART1, USART_IT_IDLE);

}

USART2中断服务函数

void USART2_IRQHandler(void)

{

u16 DATA_LEN;

u16 i;

if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //如果为空闲总线中断

{

DMA_Cmd(DMA1_Channel6, DISABLE);//关闭DMA,防止处理其间有数据

//USART_RX_STA = USART1->SR;//先读SR,然后读DR才能清除

//USART_RX_STA = USART1->DR;

DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel6);

if(DATA_LEN > 0)

{

while(USART2_TX_Finish==0)//等待数据完成才下一次

{

;

}

//将数据送DMA存储地址

for(i=0;i<DATA_LEN;i++)

{

USART2_SEND_DATA=USART2_RECEIVE_DATA;

}

//USART用DMA传输替代查询方式发送,克服被高优先级中断而产生丢帧现象。

DMA_Cmd(DMA1_Channel7, DISABLE); //改变datasize前先要禁止通道工作

DMA1_Channel7->CNDTR=DATA_LEN; //DMA1,传输数据量

USART2_TX_Finish=0;//DMA传输开始标志量

DMA_Cmd(DMA1_Channel7, ENABLE);

}

//DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据

DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);//清标志

DMA1_Channel6->CNDTR = 512;//重装填

DMA_Cmd(DMA1_Channel6, ENABLE);//处理完,重开DMA

//读SR后读DR清除Idle

i = USART2->SR;

i = USART2->DR;

}

if(USART_GetITStatus(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错

{

USART_ClearITPendingBit(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE);

}

USART_ClearITPendingBit(USART2, USART_IT_TC);

USART_ClearITPendingBit(USART2, USART_IT_IDLE);

}

DMA1_Channel5中断服务函数

void DMA1_Channel5_IRQHandler(void)

{

DMA_ClearITPendingBit(DMA1_IT_TC5);

DMA_ClearITPendingBit(DMA1_IT_TE5);

DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据

DMA1_Channel5->CNDTR = 580;//重装填

DMA_Cmd(DMA1_Channel5, ENABLE);//处理完,重开DMA

}

DMA1_Channel6中断服务函数

void DMA1_Channel6_IRQHandler(void)

{

DMA_ClearITPendingBit(DMA1_IT_TC6);

DMA_ClearITPendingBit(DMA1_IT_TE6);

DMA_Cmd(DMA1_Channel6, DISABLE);//关闭DMA,防止处理其间有数据

DMA1_Channel6->CNDTR = 580;//重装填

DMA_Cmd(DMA1_Channel6, ENABLE);//处理完,重开DMA

}

DMA1_Channel4中断服务函数

//USART1使用DMA发数据中断服务程序

void DMA1_Channel4_IRQHandler(void)

{

DMA_ClearITPendingBit(DMA1_IT_TC4);

DMA_ClearITPendingBit(DMA1_IT_TE4);

DMA_Cmd(DMA1_Channel4, DISABLE);//关闭DMA

USART1_TX_Finish=1;//置DMA传输完成

}

DMA1_Channel7中断服务函数

//USART2使用DMA发数据中断服务程序

void DMA1_Channel7_IRQHandler(void)

{

DMA_ClearITPendingBit(DMA1_IT_TC7);

DMA_ClearITPendingBit(DMA1_IT_TE7);

DMA_Cmd(DMA1_Channel7, DISABLE);//关闭DMA

USART2_TX_Finish=1;//置DMA传输完成

}呵呵,全部完,但是程序在开始启动时会出现自己发几个不知道什么字符,之后一切正常。如有什么问题,请大神指教。个人认为问题不大,因为在工作的时候通过STM32访问后台或者后台访问STM32大量的间隔密的数据时没有出现问题。而如果没有使用DMA,单帧数据发收可以,多帧数据经过USART1转USART2,就收不到从USART2反馈的第二帧数据了。不一定是速度上的问题,可能是我处理顺序的问题,但是不管是巧合,还是瞎撞的,总归解决办法的就是好办法。

工程下载地址:http://115.com/file/dpj82l3j#

USART_DMA_Interrupt.rar

说明文档下载地址:http://115.com/file/dpj8i8ov#

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

lollipop 发表于 2012-7-14 23:36:33

如果你是用STM32F0的话,哈哈,就有更好的方法啦。

USART有超时中断或帧尾检测

akwkevin2011 发表于 2012-7-14 23:50:50

lollipop 发表于 2012-7-14 23:36 static/image/common/back.gif

如果你是用STM32F0的话,哈哈,就有更好的方法啦。

USART有超时中断或帧尾检测 ...

说的我心痒痒的,可木有办法啊,不能改变硬件了。真想买一块试一下,可惜公司太抠门了。

dosomething 发表于 2012-7-15 00:33:40

说明文档无法下载啊

yzhu 发表于 2012-7-15 00:52:08

请问串口中断处理中的最后两条语句是作什么用?

USART_ClearITPendingBit(USART1, USART_IT_TC);

USART_ClearITPendingBit(USART1, USART_IT_IDLE);

wuguoyan 发表于 2012-7-15 01:02:18

好东西,支持下~~~

jiaowoxiaolu 发表于 2012-7-15 01:09:36

mark!{:lol:}{:lol:}{:lol:}

akwkevin2011 发表于 2012-7-15 02:42:39

dosomething 发表于 2012-7-15 00:33 static/image/common/back.gif

说明文档无法下载啊

已修复。

akwkevin2011 发表于 2012-7-15 02:43:54

yzhu 发表于 2012-7-15 00:52 static/image/common/back.gif

请问串口中断处理中的最后两条语句是作什么用?

USART_ClearITPendingBit(USART1, USART_IT_TC);

USART_Cle ...

清中断标记。

tiancaigao7 发表于 2012-7-15 08:50:35

lollipop 发表于 2012-7-14 23:36 static/image/common/back.gif

如果你是用STM32F0的话,哈哈,就有更好的方法啦。

USART有超时中断或帧尾检测 ...

确实,F0有超时中断,这个连F4都没有。看来后出的芯片功能就是完善呀。

lollipop 发表于 2012-7-15 09:51:56

tiancaigao7 发表于 2012-7-15 08:50 static/image/common/back.gif

确实,F0有超时中断,这个连F4都没有。看来后出的芯片功能就是完善呀。

嗯,有时候追新当小白鼠还是有好处的。

这个功能我已经用上了。

做modbus简单方便。

njchenmin 发表于 2012-7-15 15:05:10

串口超时中断是不是M0的有的呀,芯唐的M0516也有,做MODBUS确实爽!

yzhu 发表于 2012-7-15 23:22:23

再次请问:为什么要清TC中断标记?

akwkevin2011 发表于 2012-7-16 08:43:18

yzhu 发表于 2012-7-15 23:22 static/image/common/back.gif

再次请问:为什么要清TC中断标记?

呵呵,也是哦,应该清接收完成中断,当时复制别人的代码,没注意,也没出错就这样搞了,我回去注释掉试一下,如果没有问题就是不要。

lovelywwei 发表于 2012-7-16 18:05:59

嗯,值得一试。支持。

akwkevin2011 发表于 2012-7-16 19:19:03

akwkevin2011 发表于 2012-7-16 08:43 static/image/common/back.gif

呵呵,也是哦,应该清接收完成中断,当时复制别人的代码,没注意,也没出错就这样搞了,我回去注释掉试一 ...

这句不要。

//USART_ClearITPendingBit(USART1, USART_IT_TC);

呵呵,态度很严谨啊,向你学习。

deny 发表于 2012-8-6 21:26:01

,不错,值得学习的方法

zhangdawei 发表于 2012-8-10 16:26:22

mark 谢谢楼主

学生尧 发表于 2012-8-10 18:00:42

学习了,谢谢楼主

am869943552 发表于 2012-8-11 12:20:08

MARK!{:lol:}

caesar_song 发表于 2012-8-29 14:52:30

小阿福 发表于 2012-8-29 17:26:50

果断MARK

yangzi8000 发表于 2012-8-29 21:46:41

markmark

ddz123abcdef 发表于 2012-8-30 21:39:18

下来学习,谢谢楼主!

xiaoshidu 发表于 2012-9-2 21:59:03

好文,学习了!

BeichenPeng 发表于 2012-9-2 22:12:36

不错!MARK

nazily215 发表于 2012-9-3 10:18:15

我觉得使用这种超时中断或者F0的中断检测会存在一些缺陷问题:

1,如果发送机器是一个高速的机器,缓存中已经拼好了几帧或者几十帧的数据准备向UART发送。在它发送期间,很有可能会不间断而连续发送,形成“只有一帧”的这种假像,在接收方看来,由於这种帧是不断地,所以不一定会引起定时器的复位,或者F0的中断检测(其实我不太懂F0的中断检测机制,如果F0的中断检测仅仅是以一帧超时来算的话,也会引起同样的问题)。这时,接收方只能一直接收,当缓存小的时候,就会覆盖掉原来的数据,这样会有问题。

2,其中解决的方法不需要太复杂,使用内部定时器隔段时间检测DMA接收到的个数就可以了。例如,如果使用9600通信,最大10字节,那麽你可能就会每接收5个字节为超时时间来检测,即5MS会检测一下DMA的接收个数(按连续接收来说,会接收到5个字节),如果>=10个字节的话,赶紧撤出缓存进行处理。而且,这种结构对环形缓存来说也合适,并不需要在运行时改动RXDMA~

akwkevin2011 发表于 2012-9-3 14:59:01

nazily215 发表于 2012-9-3 10:18 static/image/common/back.gif

我觉得使用这种超时中断或者F0的中断检测会存在一些缺陷问题:

1,如果发送机器是一个高速的机器,缓存中已 ...

你说的这种情况是在DMA缓存长度小于数据长度的情况下,解决方法1:如阁下所说的,定时取数据,然后清空DMA,这个时候会涉及到几帧拼成一帧或者多帧的问题。解决方法2:可以增大DMA的缓存空间,最大可以设置为65535(当然具体情况具体分析),将一次数据全部收过来,这个时候涉及到的就是将帧分成几帧的问题。一般来说数据帧都会有头文件和尾文件,至于拼帧和解帧都不是问题。关键在于不丢帧。个人认为解帧更容易一些。如果是一个高速发送的机器,只要在下一次收到数据前从DMA取出来即可。

akwkevin2011 发表于 2012-9-3 15:00:16

nazily215 发表于 2012-9-3 10:18 static/image/common/back.gif

我觉得使用这种超时中断或者F0的中断检测会存在一些缺陷问题:

1,如果发送机器是一个高速的机器,缓存中已 ...

另外我这个是空闲总线接收,不是定时器接收。

nazily215 发表于 2012-9-3 17:08:39

akwkevin2011 发表于 2012-9-3 14:59 static/image/common/back.gif

你说的这种情况是在DMA缓存长度小于数据长度的情况下,解决方法1:如阁下所说的,定时取数据,然后清空DM ...

缓存MCU只有20-64KB,建议不要轻易放大DMA缓存,毕竟资源不是有限的,况且,往那么大缓存的话,使用效率可能不高。

nazily215 发表于 2012-9-3 17:10:07

akwkevin2011 发表于 2012-9-3 15:00 static/image/common/back.gif

另外我这个是空闲总线接收,不是定时器接收。

嗯,DMA这种是总线空闲接收。那向上层通知接收完的触发机制是?

akwkevin2011 发表于 2012-9-3 19:40:39

nazily215 发表于 2012-9-3 17:10 static/image/common/back.gif

嗯,DMA这种是总线空闲接收。那向上层通知接收完的触发机制是?

空闲总线中断是USART的,触发机制是串口总线上空闲了,即无数据在接收。只不过数据是用DMA方式接收,中断处理程序还在在USART中,需要重新给DMA赋值。

akwkevin2011 发表于 2012-9-3 19:43:37

nazily215 发表于 2012-9-3 17:08 static/image/common/back.gif

缓存MCU只有20-64KB,建议不要轻易放大DMA缓存,毕竟资源不是有限的,况且,往那么大缓存的话,使用效率 ...

呵呵,你说的是,不过具体情况具体分析,如果这个模块只负责转发数据和一些分割数据和组合数据的话,DMA大点也是可以的。

nazily215 发表于 2012-9-3 20:34:33

akwkevin2011 发表于 2012-9-3 19:40 static/image/common/back.gif

空闲总线中断是USART的,触发机制是串口总线上空闲了,即无数据在接收。只不过数据是用DMA方式接收,中断 ...

那試下跑壓力測試吧,跑得過的話就沒問題了,PC使用工具一直向下位機發數據~~

akwkevin2011 发表于 2012-9-3 21:11:27

nazily215 发表于 2012-9-3 20:34 static/image/common/back.gif

那試下跑壓力測試吧,跑得過的話就沒問題了,PC使用工具一直向下位機發數據~~ ...

早测试过了,OK的,数据密度忘记了,一般产品的速度够了。

adce 发表于 2012-9-4 02:20:12

这么慢的频率下的确需要DMA

znsword 发表于 2012-9-7 17:49:25

我在STM32F0 Discovery板上移植了你写的程序。功能是实现了,但是DMA1_Channel5接收完成中断总是进不去。而且我有点疑问,有了IDLE中断之后还需要Channel5的发送完成中断吗?

另外,在F0系列里面找不到

i = USART2->SR;

i = USART2->DR;

但是有USART_ClearITPendingBit(USART2, USART_IT_IDLE);

这两句有什么区别吗?

akwkevin2011 发表于 2012-9-7 20:54:33

DMA1_Channel5接收完成中断是在缓冲区接收满了才会进入,而我在USART2中断里重新给DMA1_Channel5赋予计数,也就是说只要帧长不超过缓冲区长度是不会进入DMA1_Channel5接收完成中断。

在USART_DR寄存器中写入了最后一个数据字后,在关闭USART模块之前或设置微控制器进入低功耗模式之前,必须先等待TC=1。

使用下列软件过程清除TC位:

1.读一次USART_SR寄存器;

2.写一次USART_DR寄存器。

在USART_DR寄存器中写入最后一个数据字后,要等待TC=1,它表示最后一个数据帧的传输结束。当需要关闭USART或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。

USART_ClearITPendingBit(USART2, USART_IT_IDLE);是清空闲总线中断标志位。

akwkevin2011 发表于 2012-9-7 20:54:59

znsword 发表于 2012-9-7 17:49 static/image/common/back.gif

我在STM32F0 Discovery板上移植了你写的程序。功能是实现了,但是DMA1_Channel5接收完成中断总是进不去。而 ...

DMA1_Channel5接收完成中断是在缓冲区接收满了才会进入,而我在USART2中断里重新给DMA1_Channel5赋予计数,也就是说只要帧长不超过缓冲区长度是不会进入DMA1_Channel5接收完成中断。

在USART_DR寄存器中写入了最后一个数据字后,在关闭USART模块之前或设置微控制器进入低功耗模式之前,必须先等待TC=1。

使用下列软件过程清除TC位:

1.读一次USART_SR寄存器;

2.写一次USART_DR寄存器。

在USART_DR寄存器中写入最后一个数据字后,要等待TC=1,它表示最后一个数据帧的传输结束。当需要关闭USART或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。

USART_ClearITPendingBit(USART2, USART_IT_IDLE);是清空闲总线中断标志位。

znsword 发表于 2012-9-7 23:22:49

akwkevin2011 发表于 2012-9-7 20:54 static/image/common/back.gif

DMA1_Channel5接收完成中断是在缓冲区接收满了才会进入,而我在USART2中断里重新给DMA1_Channel5赋予计数 ...

多谢!有点明白了。

1.读一次USART_SR寄存器;

2.写一次USART_DR寄存器。

作用跟

USART_ClearITPendingBit(USART2, USART_IT_TC);

是差不多的。

llq_ARM 发表于 2012-9-10 18:35:49

怎么下载不了啊?哪位能发份给我吗,正在调这个USART,谢谢啊

ZCLiu 发表于 2012-9-10 20:30:07

不错不错,学习中

jiang47 发表于 2012-9-10 21:46:36

我在STM32F4里也用的这种总线空闲中断,不过和楼主的有所不同,串口接收发送都是DMA,

DMA发送完成中断;

接收是循环模式,没开中断,初始化后就一直没管了;

串口就开空闲中断,在中断里就给个标志变量,在主程序中直接查这个标志变量就知道有没有收到一帧数据。

jiang47 发表于 2012-9-10 21:50:30

我在STM32F4里面也用了这种总线空闲中断,不过和楼主的有所不同,串口数据接收发送都是DMA,

发送完成开中断;

接收是循环模式,初始化后就没管了;

串口就开个空闲中断,中断里就给个标志变量,在主程序中查询这个变量就知道有没有收到一帧数据了。

akwkevin2011 发表于 2012-9-11 12:27:18

jiang47 发表于 2012-9-10 21:50 static/image/common/back.gif

我在STM32F4里面也用了这种总线空闲中断,不过和楼主的有所不同,串口数据接收发送都是DMA,

发送完成开中断 ...

呵呵,我提个疑问,要是数据连收到两帧呢?

akwkevin2011 发表于 2012-9-11 12:31:22

llq_ARM 发表于 2012-9-10 18:35 static/image/common/back.gif

怎么下载不了啊?哪位能发份给我吗,正在调这个USART,谢谢啊

程序重新上传:

jiang47 发表于 2012-9-11 13:43:30

akwkevin2011 发表于 2012-9-11 12:27 static/image/common/back.gif

呵呵,我提个疑问,要是数据连收到两帧呢?

你说的接连收到2帧是nazily215所说的情况?就是2帧数据变成了一帧;

还有种就是我收到一帧了,标志位置位了,但是我主程序还没进入串口处理部分,这个时候又收到一帧,就是2次置位了标志位,这种情况因该也是没问题的,解析时一样可以判断出来。

DMA接收区域超过2个帧长,在给2个变量,一个用来指示我已经读到接收区域的位置(就是上次处理完的位置),还一个变量用来指示当前接收的位置,这样应该可以啊。

bbl 发表于 2012-9-11 22:51:30

为什么用STM32F207在

DMA DISABLE后再ENABLE 就再也ENBALE不了,手册上提到 READ LOW,但还是不行

DMA_Cmd(DMA1_Stream2, DISABLE);

DMA_SetCurrDataCounter(DMA1_Stream2,PC_BUFL);

DMA_Cmd(DMA1_Stream2, ENABLE);

akwkevin2011 发表于 2012-9-12 08:30:43

没搞过207,有推荐的开发板么?

xml2028 发表于 2012-9-12 08:42:59

不错,值得学习的方法

bbl 发表于 2012-9-12 08:48:32

没买过开发板,对着官网原理图做的PCB

但我想407应该是一样的

nazily215 发表于 2012-9-12 09:00:17

akwkevin2011 发表于 2012-9-3 21:11 static/image/common/back.gif

早测试过了,OK的,数据密度忘记了,一般产品的速度够了。

我用空閒也實測了一下,當上層不斷地發送數據,即使是9600波特率,也會導致DMA不斷接收,環形緩沖的話只會覆蓋掉原來的數據,不會產生空閒中斷,所以?

請教一下你的壓力測試是不是一直發數據?用什麼工具測?(有試過用PC工具每1ms發1K個數據,9600之類的?)

但如果有接收一旦出現空閒的話,空閒中斷的方法是很好的。

akwkevin2011 发表于 2012-9-12 10:35:31

nazily215 发表于 2012-9-12 09:00 static/image/common/back.gif

我用空閒也實測了一下,當上層不斷地發送數據,即使是9600波特率,也會導致DMA不斷接收,環形緩沖的話只 ...

我又修改了一下,在DMA完成中断的时候,将DMA的数据全部发出去,这个类似于定长发送形式,并且按照你的方法测试,能发,但是发的速度都没有收的快,数据会出错啊。

这是我改过以后的程序:,求指教如何保护发送的数据不出错。

nazily215 发表于 2012-9-12 13:52:25

akwkevin2011 发表于 2012-9-12 10:35 static/image/common/back.gif

我又修改了一下,在DMA完成中断的时候,将DMA的数据全部发出去,这个类似于定长发送形式,并且按照你的方 ...

粗略看了一下你代碼,有幾點建議一下:

1)你的ISR竟然使用WHILE(1)循環?不妨拖到main函數裏執行?這樣其他中斷能進入,如果你很很充分考慮了優先級問題,累不?或者,出錯了,能調得出來?

2)關於數據出錯推測:A.你的接收是用DMA,然後通過IDLE中斷再進行處理,而且是在ISR裏面做的。B.在ISR裏,你用到了WHILE(1)為的是等TX DMA完成,在此時你又想保證數據接收正確,所以關了RX的DMA。C.直到TX DMA發送完成,把RX DMA的緩存數據向TX DMA緩存起來,準備下一輪的發送。

3)上面B直接導致了問題:其中嚴重的是關了RX DMA,你為的是確保接收正確,的確,接收是正確了,但接收不一定完整,大可能是少了的,在你WHILE的時候,很可能會存在RX有數據進來的情況,而且由於關了RX DMA而不被拿走,不妨檢測一下OVR標誌驗證一下?雖然我沒幫你驗證。

4)發送沒有接收的快,不大清楚你是怎麼測知的。不過通過代碼推,你都是接收完再發送,並在發送時關接收,這樣重複,這無形是一個半雙工狀態,如果你跑測試工具(PC一直發數據),肯定跑不過,會丟一半的包,難道這就是你說的發送沒接收的快?

5)至於出錯就是由於B的原因了。

個人意見,僅供參考,畢竟我沒細讀,只是大致瀏覽。嘿~

nazily215 发表于 2012-9-12 13:58:10

jiang47 发表于 2012-9-11 13:43 static/image/common/back.gif

你说的接连收到2帧是nazily215所说的情况?就是2帧数据变成了一帧;

还有种就是我收到一帧了,标志位 ...

其實有一個可能對你產品不會存在,但理論上一定有的問題,就是,當我把你的數據幀拉到超過你的DMA緩沖(或者把“N個幀”拼成“1個幀”),然後再發給你,會出現什麼情況?IDLE中斷是不會通知你的,這時?

Achin 发表于 2012-9-12 15:45:57

nazily215 发表于 2012-9-3 10:18 static/image/common/back.gif

我觉得使用这种超时中断或者F0的中断检测会存在一些缺陷问题:

1,如果发送机器是一个高速的机器,缓存中已 ...

我觉得在设计系统的时候,串口的帧间隔是要考虑的,一个字节或者两个字节的帧间隔做进去,实现起来不难,后面做关联应用的时候会方便

akwkevin2011 发表于 2012-9-14 11:30:07

nazily215 发表于 2012-9-12 13:52 static/image/common/back.gif

粗略看了一下你代碼,有幾點建議一下:

1)你的ISR竟然使用WHILE(1)循環?不妨拖到main函數裏執行?這 ...

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

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

回复4、关于你说的半双工状态,mcu收到数据肯定要处理了,处理数据的话,没收完,能处理吗?(程序中的转发过程等效于实际的处理过程)

回复1、有了回复4这个理由,当然需要判断处理完成没有,因此有了你说的那个while(1),等待数据处理完成。

回复2、3,呵呵,就是你说的这样,但是我也不知道如何处理了。数据一直不断的来,我又需要不断的取出来,取数据的过程还在进数据,只有取的不够快(我这明显慢一些,要出问题),取的肯定是不准的。这个时候空闲总线检测已经失效,那如果实际真那么密集的数据量,那就不能用空闲总线了,还不如就用接收中断,然后用个计数器(或者阁下所说的定时器),取数据即可。

akwkevin2011 发表于 2012-9-14 11:30:48

Achin 发表于 2012-9-12 15:45 static/image/common/back.gif

我觉得在设计系统的时候,串口的帧间隔是要考虑的,一个字节或者两个字节的帧间隔做进去,实现起来不难, ...

恩恩,同意阁下的观点。

nazily215 发表于 2012-9-14 12:57:40

akwkevin2011 发表于 2012-9-14 11:30 static/image/common/back.gif

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

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

了解乒乓模式,或者雙緩衝?直接把一個大內存分成2半,用過半中斷吧,DMA是有的,我經常用。一旦用了就變成了雙緩沖了,而且也結合了環形緩沖的特點。這樣就可以很大機會避免WHILE(1),半雙工狀態之類的。至於絕對避免,加幾個變量吧。

stely 发表于 2012-9-14 13:13:46

mark 学习

llq_ARM 发表于 2012-9-15 10:54:51

akwkevin2011 发表于 2012-9-11 12:31 static/image/common/back.gif

程序重新上传:

非常感谢

qq逆水舟 发表于 2012-9-15 16:30:35

学习下{:smile:}

akwkevin2011 发表于 2012-9-17 17:03:42

本帖最后由 akwkevin2011 于 2012-9-17 17:21 编辑

nazily215 发表于 2012-9-12 13:58 static/image/common/back.gif

其實有一個可能對你產品不會存在,但理論上一定有的問題,就是,當我把你的數據幀拉到超過你的DMA緩沖( ...

非常谢谢nazily215,代码写出来了,用环形DMA方式+空闲总线中断+完成接收中断检测超长,并用任务块的形式将每次收到的数据信息(保存在环形DMA的起始位置)按照任务形式存起来,在发送机制里面一个一个按顺序发,相当于把DMA分成一段一段。

哈哈,估计我程序里面用20个任务块过多了,估计用阁下所说的乒乓就够用。

程序1:,在秒中断里用查询方式查找是否超长,超过512长度,就将其保存起来,可以很准确的保证数据不会超过512,等待发送。

程序2:,在DMA完成接收,过半接收中断里查询数据是否超长,这个时候不能保证数据长度一定是512,介于512-1024之间,(忘了被自己改过了,不是前一句所描述的,是进入了此中断就保存一次数据,改过前的放在程序3)因此所以才会有程序1出现,我又不知道如何在这里面怎么处理了,不可能刚好512就中断吧。

程序3:

这两个经过测试,可用。

还参照了Ya Dan的例程《STM32串口驱动(环形队列+内存动态分配+DMA+拼音检索)》,按照他的思路需要将收到的数据存起来(另外开闭内存空间,涉及到内存空间管理)(这样的程序看的很帅)。

本人还是菜鸟,先不把内存管理移植上来,打算自己写一个。(附,他的程序貌似还有bug,有兴趣自行查找,我上传在此)。

akwkevin2011 发表于 2012-9-17 17:05:39

一时高兴,忘了给代码做注释了,抱歉,过一久就补上。

trave_yang 发表于 2012-10-5 10:11:09

很不错的资料啊,严重mark

LK9286 发表于 2012-10-9 15:15:34

收藏!!!

yuxinxb13 发表于 2012-10-15 09:50:18

留着学习

{:smile:}

lyg407 发表于 2012-10-17 13:06:34

{:lol:}不错, 不错。学习了。

im叶飞 发表于 2013-3-15 21:17:42

多谢 ps115真无节操

jswd0810 发表于 2013-3-16 07:13:53

mark,学习

Cavyndee 发表于 2013-3-23 12:01:30

根据来配置,实现了USART+DMA的接收,串口助手调试通过 感谢LZ

32446975 发表于 2013-4-17 00:02:29

曾经做测试,串口空闲中断作为数据帧超时检测的方法,认为行不通,放弃了这个方法.现在要再研究下这个方法了.

dayaue 发表于 2013-4-17 23:11:52

mark下来,好好研究

athlonz 发表于 2013-4-17 23:16:37

MARK一下,有空看看

zxm19820916 发表于 2013-4-27 10:15:31

lollipop 发表于 2012-7-14 23:36 static/image/common/back.gif

如果你是用STM32F0的话,哈哈,就有更好的方法啦。

USART有超时中断或帧尾检测 ...

我目前正在使用STM32F0芯片,要实现Modbus RTU从站功能,目前是使用串口中断接收。单独测试Modbus功能正常。但是和系统其他功能一起跑,Modbus经常会出错。所以想使用DMA来进行接收和发送,释放CPU。可以把你的代码或者思路发给我参考下吗?

emai:zxm0916@qq.com

谢谢!

TONG-LONG 发表于 2013-5-13 09:54:34

mark 学习

eyeman 发表于 2013-5-13 11:58:42

mark,学习

worldsing 发表于 2013-5-13 22:10:00

没有硬件fifo就是麻烦

pwstpwst 发表于 2013-7-16 22:27:17

按楼主改后程序,串口助手实现少量数据的简单收发,可是当数据加大,比如一帧80个字节,100ms连续发送就会出错,是什么原因造成的呢?

jinchenaquarius 发表于 2013-7-19 09:51:47

楼主好人拉

xlqiang 发表于 2013-9-3 20:38:44

akwkevin2011 发表于 2012-9-17 17:03 static/image/common/back.gif

非常谢谢nazily215,代码写出来了,用环形DMA方式+空闲总线中断+完成接收中断检测超长,并用任务块的形式 ...

这几个版本,哪一个是比较好用的啊?

wsfry 发表于 2013-9-9 16:56:54

文件无法下载

wzhenhua 发表于 2013-9-14 14:37:27

值得研究研究

wzhenhua 发表于 2013-9-15 09:38:00

DMA1_Channel6->CNDTR = 580;//重装填

为什么是580?

akwkevin2011 发表于 2013-9-20 20:17:14

wzhenhua 发表于 2013-9-15 09:38 static/image/common/back.gif

DMA1_Channel6->CNDTR = 580;//重装填

为什么是580?

不好意思,应该是错了,512吧.

akwkevin2011 发表于 2013-9-20 20:19:58

xlqiang 发表于 2013-9-3 20:38 static/image/common/back.gif

这几个版本,哪一个是比较好用的啊?

几个都差不多,你自己也可以写一种.其核心点就是环形接收.

szmini2006 发表于 2013-9-20 20:24:11

这个用法不错,挺新颖

catzl7 发表于 2013-9-21 01:41:31

mark{:lol:}{:lol:}{:lol:}

wzhenhua 发表于 2013-9-23 10:26:45

单片机效率提高很多

jiangbudai 发表于 2013-10-9 21:29:39

{:lol:}很厉害!

chxaitz 发表于 2013-11-9 17:32:56

mark!^_^

li3p 发表于 2013-11-9 17:40:04

这个方法真心不错,收藏。

2427295 发表于 2013-11-26 11:00:29

mark 好东西

wushifeng 发表于 2013-12-13 17:15:20

标记一下。细看

longbiao1218 发表于 2014-1-5 11:17:47

mark 整在为串口犯愁呢

esdart 发表于 2014-1-10 14:51:54

worldsing 发表于 2013-5-13 22:10

没有硬件fifo就是麻烦

你用过之后就会发现,原来这个比FIFO好用多了。

dzf050727 发表于 2014-1-14 17:56:42

MARK MARK

kobe1217241530 发表于 2014-1-14 20:51:10

楼主真是有爱啊。赞一个

fyy 发表于 2014-1-20 16:45:28

akwkevin2011 发表于 2012-7-14 23:50

说的我心痒痒的,可木有办法啊,不能改变硬件了。真想买一块试一下,可惜公司太抠门了。 ...

F0这么好啊!

dxhuo 发表于 2014-2-5 10:20:38

请教楼主一个问题,为仿照你的例程做的串口2的通讯,但是当stm32上电时,通讯异常,按一下复位键通讯就正常了,不知道是怎么回事!启动方式也是没问题的,重新上电和按复位按键有区别吗?谢谢!

页: [1] 2

查看完整版本: STM32实现USART+DMA接收未知长度的数据和发送
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: