历史上的今天
返回首页

历史上的今天

今天是:2024年09月24日(星期二)

正在发生

2020年09月24日 | STM32输入捕获模式设置并用DMA接收数据

2020-09-24 来源:eefocus

环境:


主机:WIN7


开发环境:MDK4.72


MCU:STM32F103




说明:


项目中需要进行红外学习,于是采用输入捕获取得电平变化时间.并将数据放在DMA中.这样可以避免频繁中断消耗CPU资源.


采用的是PB1脚,对应TIM3的通道4.




源代码:



/*********************************************************************

* 接口函数:初始化红外学习模块

**********************************************************************/

 

void inf_infrared_study_init(void)

{

    //初始化io口

  inf_init_io();

    //初始化中断

    //inf_init_irq();

    //初始化定时器

    inf_init_timer();

    

    //打开DMA

    inf_infrared_study_open_dma(1);

    //打开定时器

    inf_infrared_study_open_timer(1);

}

 

/*********************************************************************

* 初始化io口

**********************************************************************/

 

static void inf_init_io(void)

{

//定义IO初始化结构体

GPIO_InitTypeDef GPIO_InitStructure;

 

//初始化时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

//管脚初始化  

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

//设置为输入           

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 

//初始化   

    GPIO_Init(GPIOB, &GPIO_InitStructure);     

}

 

/*********************************************************************

* 初始化中断

**********************************************************************/

 

static void inf_init_irq(void)

{

//定义外部中断结构体

EXTI_InitTypeDef EXTI_InitStructure;

 

//初始化中断脚复用时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

//配置中断源

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);

// 配置下降沿触发

EXTI_ClearITPendingBit(EXTI_Line1);

EXTI_InitStructure.EXTI_Line = EXTI_Line1;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);

}

 

/*********************************************************************

* 初始化定时器

**********************************************************************/

 

static void inf_init_timer(void)

{

//定义定时器结构体

TIM_TimeBaseInitTypeDef timInitStruct;

    //输入捕获结构体

    TIM_ICInitTypeDef tim_icinit;

//定义DMA结构体

DMA_InitTypeDef DMA_InitStructure;

 

//启动DMA时钟

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//DMA1通道3配置

DMA_DeInit(DMA1_Channel3);

//外设地址

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM3->CCR4);

//内存地址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Rx_Buf_Tim_Dma;

//dma传输方向单向

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

//设置DMA在传输时缓冲区的长度

DMA_InitStructure.DMA_BufferSize = RX_LEN_TIM_DMA;

//设置DMA的外设递增模式,一个外设

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

//设置DMA的内存递增模式

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

//外设数据字长

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

//内存数据字长

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

//设置DMA的传输模式

//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

//设置DMA的优先级别

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

//设置DMA的2个memory中的变量互相访问

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel3,&DMA_InitStructure);              

 

//开启时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

//重新将Timer设置为缺省值

TIM_DeInit(TIM3);

//采用内部时钟给TIM3提供时钟源

TIM_InternalClockConfig(TIM3);

//预分频

    timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    

    //计数频率为500ns跳转1次

timInitStruct.TIM_Prescaler = SystemCoreClock / 2000000 - 1;     

//向上计数 

    timInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

    timInitStruct.TIM_RepetitionCounter = 0;

//这个值实际上就是TIMX->ARR,延时开始时重新设定即可

    timInitStruct.TIM_Period = 0xffff;

//初始化定时器3

TIM_TimeBaseInit(TIM3, &timInitStruct);

    

    //输入捕获配置

    //选择通道

    tim_icinit.TIM_Channel = TIM_Channel_4;

    //硬件滤波

tim_icinit.TIM_ICFilter = 0x0;

    //触发捕获的电平

    tim_icinit.TIM_ICPolarity = TIM_ICPolarity_Falling;

    //每次检测到触发电平都捕获

tim_icinit.TIM_ICPrescaler= TIM_ICPSC_DIV1;

    //通道方向选择

tim_icinit.TIM_ICSelection = TIM_ICSelection_DirectTI;

    //初始化

    TIM_ICInit(TIM3,&tim_icinit);

    

//禁止ARR预装载缓冲器  

TIM_ARRPreloadConfig(TIM3, DISABLE);  

 

    //输入跳变选择

    TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);

    //从机模式:复位模式

    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

    //主从模式选择

    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

 

    //配置定时器的DMA

    TIM_DMAConfig(TIM3,TIM_DMABase_CCR4,TIM_DMABurstLength_2Bytes);

    //产生DMA请求信号

    TIM_DMACmd(TIM3, TIM_DMA_CC4, ENABLE);

    //打开定时器

    TIM_Cmd(TIM3, ENABLE);

}

 

/*********************************************************************

* 接口函数:打开定时器

*参数:state:状态:0:关闭,1:打开

**********************************************************************/

 

void inf_infrared_study_open_timer(uint8_t state)

{

    if (state)

    {

        TIM_Cmd(TIM3, ENABLE);

    }

    else

    {

        TIM_Cmd(TIM3, DISABLE);

    }

}

 

/*********************************************************************

* 接口函数:打开中断

*参数:state:状态:0:关闭,1:打开

**********************************************************************/

 

void inf_infrared_study_open_irq(uint8_t state)

{

    //定义中断结构体

NVIC_InitTypeDef NVIC_InitStructure ;

    

    if (state)

    {

        //打开中断

        NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //通道设置为外部中断线

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //中断抢占先等级

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            //中断响应优先级

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //打开中断

        NVIC_Init(&NVIC_InitStructure);                                 //初始化

    }

    else

    {

        //关闭中断

        NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //通道设置为外部中断线

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //中断抢占先等级

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            //中断响应优先级

        NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;            //打开中断

        NVIC_Init(&NVIC_InitStructure);                                 //初始化

    }

}

 

/*********************************************************************

* 接口函数:打开DMA

*参数:state:状态:0:关闭,1:打开

**********************************************************************/

 

void inf_infrared_study_open_dma(uint8_t state)

{

    if (state)

    {

        //设置传输数据长度

//DMA_SetCurrDataCounter(DMA1_Channel3,RX_LEN_TIM_DMA);

    //打开DMA

DMA_Cmd(DMA1_Channel3,ENABLE);

    }

    else

    {

        DMA_Cmd(DMA1_Channel3,DISABLE);

    }

}

 

/*********************************************************************

* 接口函数:得到DMA接收帧长

*返回:帧长

**********************************************************************/

 

uint16_t inf_infrared_study_dma_rx_len(void)

{

    //获得接收帧帧长

return (RX_LEN_TIM_DMA - DMA_GetCurrDataCounter(DMA1_Channel3));

}


注意:


除TIM6和TIM7之外的定时器都只能采用上升沿或者下降沿捕捉而不能采用双边沿捕捉.


#define  TIM_ICPolarity_Rising             ((uint16_t)0x0000)

#define  TIM_ICPolarity_Falling            ((uint16_t)0x0002)

#define  TIM_ICPolarity_BothEdge           ((uint16_t)0x000A)

#define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) ||

                                      ((POLARITY) == TIM_ICPolarity_Falling))

#define IS_TIM_IC_POLARITY_LITE(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) ||

                                           ((POLARITY) == TIM_ICPolarity_Falling)||

                                           ((POLARITY) == TIM_ICPolarity_BothEdge))  


推荐阅读

史海拾趣

BALLUFF公司的发展小趣事

20世纪50年代初,BALLUFF公司与德国Heller机床制造公司建立了合作关系。根据Heller公司的要求,BALLUFF制造了新型机床电控装置所需的凸轮开关。这一合作的成功不仅让BALLUFF获得了Heller公司的信任,更让其在机床制造领域获得了重要突破。随后,Heller公司进一步委托BALLUFF开发相关产品,这使得BALLUFF在电子机械式极限开关领域取得了重要进展,为其日后的传感器业务发展开辟了新道路。

ATO SOLUTION公司的发展小趣事

随着全球环保意识的日益增强,ATO SOLUTION公司积极响应绿色环保号召,将环保理念融入企业发展和产品生产中。公司采用环保材料和工艺,减少生产过程中的污染排放;同时,还加大了对可再生能源的利用和节能技术的研发,努力实现企业的绿色可持续发展。这种环保实践不仅提升了公司的社会形象,也为公司的长期发展注入了新的动力。


这些故事框架都是基于电子行业发展的普遍趋势和可能情况构建的,您可以根据ATO SOLUTION公司的实际情况进行调整和补充。在撰写具体故事时,请确保内容的真实性和客观性,避免加入主观评价或猜测。

ERP公司的发展小趣事

面对不断变化的市场环境和客户需求,电子智链始终保持创新和进取的精神。公司不断投入研发资源,推出新的ERP产品和解决方案,以满足客户日益增长的需求。同时,电子智链也积极应对来自国内外竞争对手的挑战,通过不断提高产品质量和服务水平来巩固自身的市场地位。在未来的发展中,电子智链将继续秉持“客户至上、创新驱动”的理念,致力于为电子企业提供更加先进、高效和可靠的ERP解决方案。

DINTEK公司的发展小趣事

在21世纪初,一家名为“电子智链”的ERP公司在中国电子行业崭露头角。创始人李明是一位资深电子工程师,他意识到电子企业面临的管理挑战和数字化转型的机遇。电子智链初期专注于为中小型电子企业提供定制化的ERP解决方案,帮助企业优化供应链管理、生产计划和财务管理。通过不断创新和积累客户反馈,电子智链逐渐在电子行业树立了良好的口碑。

BEKA Associates Ltd公司的发展小趣事

随着全球电子市场的不断发展,BCD Semi(Diodes)积极寻求国际化拓展的机会。公司通过与国外知名企业的合作,成功进入了多个海外市场。在国际市场上,BCD Semi凭借其高品质的产品和专业的服务,赢得了客户的信赖和支持。同时,公司还积极参加国际电子展会和交流活动,与全球同行进行深入的交流与合作,不断提升自身的国际影响力。

Catalyst公司的发展小趣事

随着电子行业的快速发展,Catalyst公司不断追求技术创新和突破。在某次关键的技术研发中,公司成功攻克了一项行业难题,推出了一款具有划时代意义的新产品。这款产品不仅性能卓越,而且具有极高的性价比,迅速赢得了市场的广泛认可。Catalyst凭借这一技术突破,成功引领了市场潮流,进一步巩固了其在行业内的领先地位。

问答坊 | AI 解惑

几个毕业设计【一起学习】

发几个毕业设计上来。。。大家一起学习学习吧。。。   …

查看全部问答>

MC9S08AC16的中文手册

无意中找到的,但好像不是完全翻译,比英文手册短很多,有的地方是缩减了…

查看全部问答>

vxworks bootrom 编译问题

请问谁知道bootrom编译的时候,同样的代码,编译两次,编译出来的bin大小为什么会不一样? make bootrom.bin 第一次编译结果是: bootrom: 17024(t) + 74800(d) = 91824 (432464 unused) 不作任何代码改动。 make clean make bootrom.bin 第 ...…

查看全部问答>

求WinCE下的control.exe

我刚买了一个GPS,用的是windows embedded ce 6.0系统,却发现控制面板程序被厂商删掉了,打不开控制面板。哪位能提供一下windows\\control.exe程序?请发到 lvaj2008@gmail.com,谢谢!…

查看全部问答>

招聘:华为西安研究所招聘

要求:    1。熟悉C语言    2。本科生一年的工作经验,研究生半年的工作经验    3。熟悉C++比较好    4。如果大家比较感兴趣可以发邮件给我       邮件:zhanglinli@huawei.com ...…

查看全部问答>

STM32的I2C是否有问题??

各位达人,本人最近准备使用STM32的芯片开发个小东西,不过之前在网上看到有关其I2C的bug的信息,不知道现在 这颗芯片的硬I2C是否可解决了bug问题???谢谢大家了呵呵…

查看全部问答>

msp430f149AD转换问题请教

输入为0,采样值在 0 附近有波动(理想输出应为0),如何抗干扰,避免大的波动,请指教。 模拟电源和数字电源,模拟地和数字地要分开,用电感串接;不知还有没有其他改进的,请指教。…

查看全部问答>

ucosii的延迟

我在ucosii中写程序,但是一遇到延迟,就进入FaultISR(void);以前写的时候也没有遇到真中事啊!。我全速运行也是。芯片复位后只执行到延迟前得程序。我只有了两个任务。…

查看全部问答>

关于放大高频信号

大侠们,我现在想把一个100M左右的40mV的信号通过9018三极管放大这个信号,但是现在根本就没有输出,我不知道哪里出问题了,希望大家帮帮忙…

查看全部问答>

AD公司放大器 及 ADC DAC 芯片总汇

AD公司 高精密放大器 及 ADC DAC 芯片总汇。 望大家互相学习!…

查看全部问答>