历史上的今天
返回首页

历史上的今天

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

正在发生

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

2020-09-24 来源:eefocus

环境:


主机:WIN7


开发环境:MDK4.72


MCU:STM32F103




说明:


项目中需要进行红外学习,如果采用输入捕获的方式,因为定时器只能捕获上升沿或者下降沿,所以只能获得周期,而不能得到具体的红外波的高低电平的时间.所以采用PWM输入的方式进行捕获.


采用的是PA8脚,对应TIM1的通道1.




源代码:



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

* 函数

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

 

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

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

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

 

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

//设置为输入           

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 

//初始化   

    GPIO_Init(GPIOA, &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通道配置

DMA_DeInit(DMA1_Channel2);

//外设地址

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM1->CCR1);

//内存地址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Rx_Buf_Tim_Dma1;

//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_Channel2,&DMA_InitStructure);   

 

    //启动DMA时钟

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//DMA1通道配置

DMA_DeInit(DMA1_Channel3);

//外设地址

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM1->CCR2);

//内存地址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Rx_Buf_Tim_Dma2;

//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_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

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

TIM_DeInit(TIM1);

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

TIM_InternalClockConfig(TIM1);

//预分频

    timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    

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

timInitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1;     

//向上计数 

    timInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

    timInitStruct.TIM_RepetitionCounter = 0;

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

    timInitStruct.TIM_Period = 0xffff;

//初始化定时器

TIM_TimeBaseInit(TIM1, &timInitStruct);

 

    //输入捕获配置

    //选择通道

    tim_icinit.TIM_Channel = TIM_Channel_1;

    //硬件滤波

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(TIM1,&tim_icinit);

    TIM_PWMIConfig(TIM1, &tim_icinit);

//禁止ARR预装载缓冲器  

//TIM_ARRPreloadConfig(TIM1, DISABLE);  

 

    //输入跳变选择

    TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1);

    //从机模式:复位模式

    TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset);

    //主从模式选择

    TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);

    

    //配置定时器的DMA

    TIM_DMAConfig(TIM1,TIM_DMABase_CCR1,TIM_DMABurstLength_2Bytes);

    //产生DMA请求信号

    TIM_DMACmd(TIM1, TIM_DMA_CC1, ENABLE);

    

    //配置定时器的DMA

    TIM_DMAConfig(TIM1,TIM_DMABase_CCR2,TIM_DMABurstLength_2Bytes);

    //产生DMA请求信号

    TIM_DMACmd(TIM1, TIM_DMA_CC2, ENABLE);

    

    //打开定时器

    TIM_Cmd(TIM1, ENABLE);

}

 

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

* 接口函数:打开定时器

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

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

 

void inf_infrared_study_open_timer(uint8_t state)

{

    if (state)

    {

        TIM_Cmd(TIM1, ENABLE);

    }

    else

    {

        TIM_Cmd(TIM1, 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_Channel2,ENABLE);

        DMA_Cmd(DMA1_Channel3,ENABLE);

    }

    else

    {

        DMA_Cmd(DMA1_Channel2,DISABLE);

        DMA_Cmd(DMA1_Channel3,ENABLE);

    }

}

 

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

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

*返回:帧长

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

 

uint16_t inf_infrared_study_dma_rx_len(void)

{

    //获得接收帧帧长

return (RX_LEN_TIM_DMA - DMA_GetCurrDataCounter(DMA1_Channel2));

}


推荐阅读

史海拾趣

Afero公司的发展小趣事

XXXX年,Afero公司成功完成了5000万美元的C轮融资,这一轮融资由私募股权公司Crosspoint Capital Partners领投,Home Depot也参与了投资。这笔资金为Afero提供了更多的研发和市场推广资源,加速了其在物联网领域的业务发展。公司利用这笔资金进一步提升了平台的技术水平,扩大了市场份额,并加强了与合作伙伴的合作关系。

Fong Ya Enterprise Co Ltd公司的发展小趣事

XXXX年,Afero公司成功完成了5000万美元的C轮融资,这一轮融资由私募股权公司Crosspoint Capital Partners领投,Home Depot也参与了投资。这笔资金为Afero提供了更多的研发和市场推广资源,加速了其在物联网领域的业务发展。公司利用这笔资金进一步提升了平台的技术水平,扩大了市场份额,并加强了与合作伙伴的合作关系。

泽耀科技(Ashining)公司的发展小趣事

在国内市场取得一定成绩后,泽耀科技(Ashining)开始积极拓展国际市场。公司参加了多个国际电子展会,与国际知名企业建立了合作关系,成功将产品打入国际市场。同时,泽耀科技还积极寻求与国际先进技术的交流与合作,不断提升自身的技术水平和产品质量。

Brainboxes公司的发展小趣事

Brainboxes一直注重与客户建立紧密的合作关系。公司深入了解客户的需求和应用场景,为其提供定制化的解决方案。此外,Brainboxes还积极参与工业连接领域的发展,与多家知名企业建立合作关系,共同推动行业的技术进步和应用创新。这种客户亲密度和工业连接能力使得Brainboxes在市场竞争中占据有利地位。

FCT electronic公司的发展小趣事

近年来,电子行业面临着成本上升、全球不稳定以及经济动荡等多重挑战。FCT electronic公司凭借其在挠性电路板领域的深厚积累,积极应对这些挑战。公司加强了对供应链的管理,提高了生产效率,降低了成本。同时,FCT electronic公司还加大了对研发的投入,推动产品向高端化、智能化方向转型升级。这些努力使FCT electronic公司在行业中保持了领先地位。

Glorious Sources Co Ltd公司的发展小趣事
由于光电传感器输出的电信号往往较弱,需要进行放大处理;同时,为了去除噪声和干扰,还需要设计合适的滤波电路。

问答坊 | AI 解惑

EMI_的诊断与抑制的几点建议

EMI_的诊断与抑制的几点建议…

查看全部问答>

pe导出函数问题

大家好:     根据导出函数表找到了addressofrunction的数组地址,并且根据addressofnameordinal和addressofname找到了相应的索引,但是有句代码我看不太懂,就是:                 ...…

查看全部问答>

如何 用单片机做USB 接口的 显示器?

主机是8051单片机,要求使用USB 连接一个显示器 显示器可以是LED 也可以是液晶的! 请问一下 现在有没有这样的技术? 有做过的指导一下!…

查看全部问答>

基于GMS段信服务的 设备监控,如何做?

基于GMS段信服务的 设备监控,如何做? 假如我现在 有几台交换机,将它们连成一串,那怎么去监控它们连通状态呢? 给点思路吧…

查看全部问答>

为什么我WINCE6。0 做 OSDesign时候没有 Emulator 啊?

我安装了: 1.vs2005 + vs2005sp1           2.wince 6.0 + pb sp1           3.device emulator 2.0           4.virtual machine connection 在 ...…

查看全部问答>

lm3s8962使用之UART篇

intmain(void){    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |                   SYSCTL_XTAL_8MHZ);&nb ...…

查看全部问答>

st7build

我连接一个C程序,出现错误:----------- Project modebox - ST7 Cosmic - Configuration Debug -------------Compiling interrupt_vector.c...cxst7 +modm +debug -pxp&nb ...…

查看全部问答>

2812把内部flash作为数据存储的问题

是这样实现吗? 先定义 #pragma DATA_SECTION(flash_data, \\"FLASH\\" cmd里 把FLASH分配到flash地址,再定义 int flash_data[20]; 对 flash_data[20]进行读写 但实际运行发现无法改变flash_data[20]中内容,请问应如何实现把flash作为 ...…

查看全部问答>

请教一个问题

一个数组,比如 int iii[200]。缺省情况下,是分配到.data段还是.bss段。一个数组算不算initiated? 谢谢!…

查看全部问答>