stm32 458最后stm32 串口第一个字节节无法正常发出

实现STM32实现串口通过DMA接收和发送未知长度的的帧? - STM32/STM8技术论坛 - 中国电子技术论坛 -
Powered by Discuz! Archiver
实现STM32实现串口通过DMA接收和发送未知长度的的帧?
本帖最后由 lotusp 于
17:54 编辑
前言:开始学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_InitS
/* 第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_InitS
/* 第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_N
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_N
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 */
void DMA_Configuration(void)
DMA_InitTypeDef DMA_InitS
/* 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 = 0x;
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_D
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B
DMA_InitStructure.DMA_Mode = DMA_Mode_C
DMA_InitStructure.DMA_Priority = DMA_Priority_H
DMA_InitStructure.DMA_M2M = DMA_M2M_D
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 = 0x;
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_D
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B
DMA_InitStructure.DMA_Mode = DMA_Mode_C
DMA_InitStructure.DMA_Priority = DMA_Priority_H
DMA_InitStructure.DMA_M2M = DMA_M2M_D
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 = 0x;
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_D
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B
DMA_InitStructure.DMA_Mode = DMA_Mode_C
DMA_InitStructure.DMA_Priority = DMA_Priority_H
DMA_InitStructure.DMA_M2M = DMA_M2M_D
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 = 0x;
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_D
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B
DMA_InitStructure.DMA_Mode = DMA_Mode_C
DMA_InitStructure.DMA_Priority = DMA_Priority_M
DMA_InitStructure.DMA_M2M = DMA_M2M_D
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_InitS
/* 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[512];
u8 USART2_SEND_DATA[512];
u8 USART1_RECEIVE_DATA[512];
u8 USART2_RECEIVE_DATA[512];
u8 USART1_TX_Finish=1;// USART1发送完成标志量
u8 USART2_TX_Finish=1; // USART2发送完成标志量
USART1中断服务函数
void USART1_IRQHandler(void)
u16 DATA_LEN;
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[i]=USART1_RECEIVE_DATA[i];
//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;
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[i]=USART2_RECEIVE_DATA[i];
//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反馈的第二帧数据了。不一定是速度上的问题,可能是我处理顺序的问题,但是不管是巧合,还是瞎撞的,总归解决办法的就是好办法。
工程下载地址:
USART_DMA_Interrupt.rar
说明文档下载地址:
STM32实现USART+DMA接收未知长度的数据和发送.rar
木子studio
不错的东西
{:23:}{:23:}{:23:}{:23:}
eyesmall007
解压后不知为何未见工程文件
没有工程文件, 稍微有点遗憾
非常好的资料,谢谢楼主分享
谢谢了、。。。。。。。。
不错,准备试试,不过对你给出的循环缓存,不大赞同
一直在弄这个串口,我是4个串口,靠命令执行。麻烦啊!
总觉得时间没有设置好。
不错,谢谢楼主
不错的东西 抢了支持
linguohuan
楼主好给力,刚好需要学习
给力学习呀,正在研究呢,这种方式不错
Billion_Years
好像有点问题 ,没有工程文件啊
谢谢楼主了,顶一下。。。。。。
初始化代码有够长的啊~~~
找好久 才找到這篇文章~~謝謝樓主
学习了,谢谢、、、、、、、、、、
学习了,不错的东西
谢谢分享,不错
查看完整版本:二次元同好交流新大陆
扫码下载App
汇聚2000万达人的兴趣社区下载即送20张免费照片冲印
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(4994)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'基于STM32 I2C的TMP101温度传感器的C源码',
blogAbstract:'&&&&&&&搞这个历程差不多花了我一个周末的时间,一片小小的TMP101确实让我破费脑筋。最后甚至使用了示波器直接观察SDA SCL 的波形。不过示波器的使用确实纠正我一个严重且低级的错误。这期间也在网上搜过STM32 的I2C 应用& 大多都是在说 STM32 的I2C固件库写的烂、STM32的硬件有问题、I2C接口没法用等等,最后解决方式都是用软件像51那样用IO口软件模拟IIC时序。但我看了STM32最新的勘误表,根本没有所谓STM32的IIC硬件设计缺陷。我可不想把STM32用的像8051一样。我要用高效的硬件I2C而且要用ST官方库来实现~!',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:4,
publishTime:5,
permalink:'blog/static/',
commentCount:7,
mainCommentCount:5,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}stm32 串口第一字节丢失问题分析_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
stm32 串口第一字节丢失问题分析
上传于||文档简介
&&S​T​M2​,​字​节​丢​失​,​丢​包​,​串​口
阅读已结束,如果下载本文需要使用
想免费下载本文?
你可能喜欢STM32 USART
RXNE中断接收位总共有几种会将其清零==
热门型号:
&&&当前位置:
STM32 USART
RXNE中断接收位总共有几种会将其清零
用户名:gfs0521
注册时间: 14:50:00
STM32 USART
RXNE中断接收位总共有几种会将其清零
本帖最后由 gfs0521 于
14:52 编辑 收到采用19200Bps,开启发送完成后产生标志TC中断和RXNE接收中断程序问题是在发送数据后 TC标志位中断产生时,2us以内也将收到RXNE标志中断,有时会导致收不到数据,RXNE只有在判断置1时才会读DR寄存器,看资料读取DR寄存器时,将自动清除RXNE标志位。所以在中断程序里没有软件清除RXNE位。疑问还有哪些情况会导致自动清除RXNE位呢?暂时解决的方法是在进入USART中断先延时5us后再判断接收中断或发送中断,测试就没有出现数据丢失的问题。
用户名:gfs0521
注册时间: 8:16:00
是否读取SR寄存器就会把RXNE标志位中断清零呢?&&香主是否帮忙分析下
用户名:香水城
注册时间: 13:12:00
我现在手头没有资料,参考手册上怎么说的?
用户名:gfs0521
注册时间: 21:23:00
资料上 读取DR寄存器时自动将其清零
用户名:香水城
注册时间: 11:26:00
LZ问的是还有哪些情况会导致自动清除RXNE位呢,我问的是资料上对你的这个问题是怎么说的?
用户名:gfs0521
注册时间: 11:48:00
资料上哪有这个问题的说明?
在发送中断产生时,还未退出中断程序时,此时产生了接收中断就会有可能丢失?
用户名:香水城
注册时间: 11:55:00
资料上哪有这个问题的说明?
在发送中断产生时,还未退出中断程序时,此时产生了接收中断就会有可能丢失?
gfs0521 发表于
用户名:gfs0521
注册时间: 11:56:00
是有时会有时不会出现丢失,我也说明了,如果延时了5us再判断就不会有问题,真是奇怪
用户名:香水城
注册时间: 13:50:00
不完全理解你的说明:“收到采用19200Bps,开启发送完成后产生标志TC中断和RXNE接收中断”,不知道你的具体操作过程的先后次序如何,所以无法判断究竟是什么问题。
用户名:gfs0521
注册时间: 13:54:00
////////////////////////////////////////////////////////////////////////////////
// Description& & : This function&&Bps:19200&&
// Input& && && & : None
// Return& && && &: None
////////////////////////////////////////////////////////////////////////////////
void Usart2_Interrupt(void)
&&unsigned short L
&&////////避免发送数据时,接收不到发送的数据,2us时就容易丢失 ******
&&////////延时5us左右,保证发送中断后,同时也接收到发送的数据
&&for(Length = 0; Length & 50; Length++) {}
&&if((USART2-&SR & USART_FLAG_RXNE) != RESET)
& & //USART2-&SR &= (~USART_FLAG_RXNE);& && && && & //向USART2-&DR读取数据将自动清零RXNE标志
& & Rxd.OverTime = USART_10MS;& && && && && && && & //延时10ms判断是否串口结束 TTT
& & Rxd.DataBuf = USART2-&DR & 0
& & ......
&&/////////检测是否为USART发送结束
&&if((USART2-&SR & USART_FLAG_TC) != RESET)
& & USART2-&SR &= (~USART_FLAG_TC);
& & if(Txd.Head == HEADING_SENDING)
& && &if(Txd.Total & 0)
& && &&&Txd.Total--;
& && &&&USART2-&DR = TxdData[Txd.FiFoTemp] & 0x00
& && &&&Txd.Result = Crc8BitTab[Txd.Result ^ TxdData[Txd.FiFoTemp]];
& && &&&Txd.FiFoTemp++;
& && &&&if(Txd.FiFoTemp &= TXD_DATA_LENGTH) Txd.FiFoTemp = 0;
& && &else
& && &&&USART2-&DR = Txd.Result & 0x00
& && &&&Txd.Head = HEADING_SENDEND;& &&&//发送结束,包括CRC校验码
用户名:gfs0521
注册时间: 13:55:00
本帖最后由 gfs0521 于
13:57 编辑
for(Length = 0; Length & 50; Length++) {}
去掉延时5us 在发送数据时,并同时接收数据很容易丢失掉一个字节
用户名:香水城
注册时间: 14:01:00
“避免发送数据时,接收不到发送的数据”这句话是什么意思?
STM32发送数据的同时,还要接收回来自己发送的数据吗?
另外,通信的另一方会在接收数据的同一时刻发送数据吗? 即整个系统是全双工的(任一方的发送和接收都是重叠的)吗?
用户名:gfs0521
注册时间: 14:22:00
通信的本身在发送时会收到自己发送的数据
TXD发送的数据经外接器件还会由RXD接收,但总线的上会有延时,所以在发送数据时TC会先产生中断,在中断程序加一个IO口变化判断,RXNE接收中断会在TC中断过后2us左右才会产生,就是基本上两个中断不是同时产生的,但有时会漏掉RXNE中断
用户名:香水城
注册时间: 16:51:00
请试试,如果有USART_FLAG_RXNE标志,处理完USART_FLAG_RXNE后直接退出中断;同样,如果有USART_FLAG_TC标志,处理完USART_FLAG_TC后也直接退出中断。
用户名:gfs0521
注册时间: 16:40:00
按照香主的方法测试了,直接退出还是会丢失数据,不知何因
热门型号:}

我要回帖

更多关于 stm32 第一个字节 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信