本办法使用定时器定时查询DMA接收到的数据,如果超过设定的周期则认为本次数据包结束,将数据拷贝到缓冲区,交由其他程序处理。可以接收任意大小的数据包,尤其适用于MODBUS等协议,曾经用于GPS、GPRS等接收,很实用。本方法占用CPU时间极少,尤其是波特率很高时,效果更加明显。
当某一个串口的数据接收超时以后,定时器中断中将数据拷贝到缓冲区,在主程序中可以判断数据标志UART1_Flag,大于0的时候即代表有数据接收到,可以处理,处理完后将此变量清零即可。
两个数据包间隔较小时,可以将定时器的周期调短些。
//超时时间定义
#define UART1_TimeoutComp 2 //20ms
#define UART2_TimeoutComp 10 //100ms
#define UART3_TimeoutComp 10 //100ms
#define SRC_USART1_DR (&(USART1->DR)) //串口接收寄存器作为源头
#define SRC_USART2_DR (&(USART2->DR)) //串口接收寄存器作为源头
#define SRC_USART3_DR (&(USART3->DR)) //串口接收寄存器作为源头
extern u16 UART1_Flag,UART2_Flag,UART3_Flag;
extern u8 uart1_data[200],uart3_data[500],uart2_data[500];
u8 UART1_Timeout,UART2_Timeout,UART3_Timeout;
u16 UART1_FlagTemp,UART2_FlagTemp,UART3_FlagTemp;
u8 uart1_data_temp[200],uart2_data_temp[500],uart3_data_temp[500];
u16 uart1_Flag_last=0,uart2_Flag_last=0,uart3_Flag_last=0;
//定时器初始化
void TimerInit(void)
{
//定时器初始化数据结构定义
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//初始化定时器,用于超时接收,20ms
//复位计数器
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = 100; //计数上限,100*100us = 10000us = 10ms
TIM_TimeBaseStructure.TIM_Prescaler = 4799; //预分频4800,48MHz主频,分频后时钟周期100us
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
//初始化
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
//清中断
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//使能定时器中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_UpdateDisableConfig(TIM2,DISABLE);
//定时器清零
TIM_SetCounter(TIM2,0);
//定时器启动
TIM_Cmd(TIM2,ENABLE);
}
//DMA初始化,只列出一个通道,其他两个通道相同
void DMA5_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel5); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_USART1_DR; //源头BUF既是 (&(USART1->DR))
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)uart1_data_temp; //目标BUF 既是要写在哪个个数组之中
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作源头//外设是作为数据传输的目的地还是来源
DMA_InitStructure.DMA_BufferSize = 200; //DMA缓存的大小 单位在下边设定
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_PeripheralDataSize_Byte; //内存字节为单位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //4优先级之一的(高优先)VeryHigh/High/Medium/Low
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存
DMA_Init(DMA1_Channel5, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道1寄存器
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); //DMA5传输完成中断
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能USART1的接收DMA请求
DMA_Cmd(DMA1_Channel5, ENABLE); //正式允许DMA
}
//串口初始化,只列出一个通道,其他两个通道相同
void USART1_Configuration(void)
{
//串口初始化数据结构定义
USART_InitTypeDef USART_InitStructure;
//初始化串口为38400,n,8,1
USART_InitStructure.USART_BaudRate = 38400 ;
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_Cmd(USART1, ENABLE);
//默认设置为输入状态
DMA5_Init();
}
//定时器中断服务程序
void TIM2_IRQHandler(void)
{
u16 i;
//清定时器中断
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
UART1_Timeout++;
UART2_Timeout++;
UART3_Timeout++;
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel5);
DMA_ClearITPendingBit(DMA1_IT_GL5); //清除全部中断标志
if(i!=uart1_Flag_last) //未完成传输
{
UART1_Timeout=0;
uart1_Flag_last=i;
}
else
{
if(UART1_Timeout>UART1_TimeoutComp) //产生超时
{
if(i<200) //有数据接收到
{
UART1_FlagTemp=200-i; //得到接收到的字节数
for(i=0;i
UART1_Flag=UART1_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC5);
DMA_Cmd(DMA1_Channel5, DISABLE); //正式允许DMA
DMA5_Init();
}
UART1_Timeout=0;
}
}
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel6);
DMA_ClearITPendingBit(DMA1_IT_GL6); //清除全部中断标志
if(i!=uart2_Flag_last) //未完成传输
{
UART2_Timeout=0;
uart2_Flag_last=i;
}
else
{
if(UART2_Timeout>UART2_TimeoutComp) //产生超时
{
if(i<500) //有数据接收到
{
UART2_FlagTemp=500-i; //得到接收到的字节数
for(i=0;i
UART2_Flag=UART2_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC6);
DMA_Cmd(DMA1_Channel6, DISABLE); //正式允许DMA
DMA6_Init();
}
UART2_Timeout=0;
}
}
//------------------------------------------------------------------
i=DMA_GetCurrDataCounter(DMA1_Channel3);
DMA_ClearITPendingBit(DMA1_IT_GL3); //清除全部中断标志
if(i!=uart3_Flag_last) //未完成传输
{
UART3_Timeout=0;
uart3_Flag_last=i;
}
else
{
if(UART3_Timeout>UART3_TimeoutComp) //产生超时
{
if(i<500) //有数据接收到
{
UART3_FlagTemp=500-i; //得到接收到的字节数
for(i=0;i
UART3_Flag=UART3_FlagTemp;
DMA_ClearFlag(DMA1_FLAG_TC3);
DMA_Cmd(DMA1_Channel3, DISABLE); //正式允许DMA
DMA3_Init();
}
UART3_Timeout=0;
}
}
}
上一篇:关于stm32 的 USB 转串口 virtual_Com_Port的例程的一些问题
下一篇:STM32F10x芯片RTC实时时钟
推荐阅读
史海拾趣
Alcatel-Lucent 的起源可以追溯到 19 世纪末的法国。1880 年,一家名为 Compagnie Générale d'Électricité (CGE) 的公司在法国成立,主要从事电信和电气设备的制造和销售。这家公司后来成为了 Alcatel-Lucent 的前身之一。
20 世纪初,CGE 开始涉足电信领域,并开始在法国和国际市场上发展。该公司逐渐成为了一家领先的电信设备制造商,并参与了许多重要的电信基础设施项目。
2006 年,法国的 Alcatel 和美国的 Lucent Technologies 公司宣布合并,成立了 Alcatel-Lucent 公司。这次合并创造了一个综合性的电信设备制造商,覆盖了通信网络、软件和服务等多个领域。
合并后,Alcatel-Lucent 成为了全球领先的电信设备供应商之一,为全球各地的电信运营商提供了广泛的产品和解决方案,包括固定和移动网络、光纤通信、宽带接入和数据中心等领域。
在成立后的几年里,Alcatel-Lucent 继续推出创新的产品和技术,包括下一代移动通信技术 LTE、IP/MPLS 网络和云计算解决方案等,为数字化时代的通信基础设施发展做出了重要贡献。
随着科技的快速发展和市场的不断变化,Crystek公司意识到只有不断创新才能保持竞争优势。因此,公司加大了研发投入,积极引进先进技术,推出了一系列具有创新性和竞争力的新产品。其中,温度补偿晶体振荡器(TCXO)和压控晶体振荡器(VCXO)等产品的推出,不仅提升了Crystek公司的技术实力,也进一步巩固了其在行业中的领先地位。同时,公司还不断优化生产工艺和质量控制体系,确保产品的高性能和可靠性。
Abundance Enterprise Company深知人才是企业发展的核心力量。因此,公司注重人才培养和团队建设工作。公司建立了完善的人才培养机制,通过内部培训、外部引进等方式不断提升员工的专业素质和综合能力。同时,公司还注重团队建设,营造积极向上、团结协作的工作氛围,为公司的持续发展提供了强大的人才保障。
请注意,上述故事均为虚构内容,不代表Abundance Enterprise Company公司的真实发展历程。如需了解该公司的真实情况,建议查阅相关资料或访问其官方网站。
随着电子行业的快速发展和变革,DURAKOOL公司也面临着新的挑战和机遇。为了保持竞争力,公司不断调整战略和业务结构,积极寻求新的增长点。在这个过程中,公司开始涉足电动汽车高压继电器等新兴市场领域,并取得了显著成果。
在1935年,DURAKOOL公司在Durakool成立,由几位电子工程师和发明家共同创立。他们的初衷是为电气和电子市场提供高质量的组件和系统。起初,公司面临着资金短缺和市场竞争激烈的挑战,但他们凭借对技术的热情和不懈的努力,逐渐开发出了一系列具有竞争力的产品,如Durakool水银继电器和功率继电器,赢得了客户的认可。
AVR_figter20090728版 AVR_fighter已经更新到20090728版,可以到www.ourdev.cn/bbs中的usb分论谈中顶置贴里查看更新或下载AVR_fighter20090728版. 新版增加了一点实用功能.如时钟效准写入flash,在flash或eeporm选项卡中进行查找......等等. OURDE ...… 查看全部问答∨ |
|
OBJS = send_voip.o fun.o main.o CrcPublic.oARCH ?= #ARCH ?= arm-hismall-linux-CC = $(ARCH)gccINC_DIR +=.SRC_DIR +=.INSTALL_PATH=../TARGET=helloCFLAGS= -Wall -g $(TARGET): $(OBJS) $(CC) $(OBJS) -o $@ $(CFLAGS) cp -f $(TA ...… 查看全部问答∨ |
|
cc2531作为协调器,然后cc2530作为节点,可以实现组网功能。现在问题是我想通过2531的usb口连接pc,此时不知道2531的驱动如何添加和使用(添加详细解释下),求大神指点。 本人小白一个,在学习中。。。求助啊 先谢过大 ...… 查看全部问答∨ |
|
花了半天时间研究了下蜂鸣器演奏乐曲的基本原理,有兴趣的朋友可以在这里讨论一下。《两只老虎》送给你,由于是楼主的处女座所以有偿奉献,望大家体谅。… 查看全部问答∨ |
1. 左右通道 刚开汽车都没喇叭,后来发达了,装了两个,听听小曲。 小朋友说:二叔车不错,听歌的时候,敲鼓的在这边,大罗的在那边了。 二叔说:这是立体声。 构造也简单,主机输出 两路线,个接一喇叭 … 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 平头哥RVB2601开源应用方案征集来啊~100套板卡助阵,天猫精灵智能套装礼品组等你抱走~
- 有奖直播|TI 使用 DLP® 微型投影技术设计增强现实智能眼镜
- 看是德科技汽车电子精彩专题,为你的出行安全打call, 下载赢好礼!
- 下载文档看视频有礼:获得更高效的PCIe一致性测试文档
- 有奖直播|TI MSP430™民用超声波水表开发指南及其智能模拟组合模块在传感器检测中的应用
- 免费样片申请、技术干货|Littelfuse数据中心解决方案专区
- 有奖直播报名:TI DLP®技术在汽车行业的创新应用——增强型抬头显示
- 【有奖直播】 聚焦语音识别核心技术,走进Microchip Timberwolf™音频处理器研讨会
- Hercules DIY创意大搜集!比比看,谁的设计最“安全”?
- 掌控5G 网络:VIAVI 与凯捷合作开展 5G 和 O-RAN 验证
- 高通面向Windows 11 PC释放Wi-Fi游戏性能
- 高通和SSW Partners达成收购维宁尔的最终协议
- Digi-Key Electronics 被 ECS Inc. International 评为全球顶级战略合作
- 瑞萨电子谈并购Dialog后在汽车市场的新机遇
- 秒杀99%的量产电动汽车?这款车的超低风阻只有0.208Cd
- Cadence发布突破性新产品 Integrity 3D-IC平台,加速系统创新
- 阿童木机器人:并联机器人助力工业自动化转型升级
- 汽车芯片:从传统分布式架构向集中式架构的演进
- 如何看待吉利旗下沃尔沃和极星的上市