STM32輸入捕獲模式設定並用DMA接收資料
阿新 • • 發佈:2018-11-15
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
STM32輸入捕獲模式設定並用DMA接收資料
本文部落格連結:http://blog.csdn.net/jdh99,作者:jdh,轉載請註明.
環境:
主機: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))