99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

ReCclay
認證:VIP會員
所在專題目錄 查看專題
藍橋嵌入式之 LCD使用
藍橋嵌入式之 簡單USART通信實現LCD顯示
藍橋嵌入式之 AT24C02
藍橋嵌入式之 PWM波輸出相關總結
藍橋嵌入式之 輸入捕獲(一)
藍橋嵌入式之 輸入捕獲(二)
作者動態 更多
【FPGA基礎】基于 Pango Design Suite(PDS) 的FPGA開發流程
2021-05-14 11:22
【FPGA基礎】基于Quartus Prime 17.1 的FPGA開發流程
2021-05-08 17:49
【AD快速入門】8051最小系統繪制
2021-04-22 10:03
藍橋嵌入式之 ADC電壓采集與顯示
2021-04-14 11:48
藍橋嵌入式之 實時時鐘RTC
2021-04-13 14:50

藍橋嵌入式之 輸入捕獲(一)

工程代碼可見Github<傳送門>


1個留待補充的程序:


避免干擾,嘗試用開關總中斷的方法

一、輸入捕獲測量原理

之前我們做的是PWM波的輸出,現在再來看PWM的輸入,即測量PWM波頻率和占空比的測量。

理解一副重要的示意圖:

圖中紫色部分為我們輸入的方波信號,首先我們剛開始時要把捕獲通道設置為上升沿觸發,假如我們捕獲到了一個上升沿,也就是到達了A點,那么我們的定時器就開始計數,隨后我們還要吧捕獲通道設置成為下降沿觸發。當我們捕獲了一個下降沿時,也就是到達了B點,那么我們獲取一個計數值,定時器還得繼續計數,同時重新把捕獲通道設置為上升沿觸發。直到再次捕獲到了一個上升沿,那么就代表已經到達C點了,我們再獲取一次計數值。

那么我們通過獲取的這兩個計數值,就很容易的算出頻率和占空比。<參考eavane大神博客>

頻率 = 1000000 / 第二次捕獲值(72分頻的前提)

占空比 = 第一次捕獲值 / 第二次捕獲值 * 100

知道了原理,再來看看具體實現吧。

二、實現代碼

main.c

/*******************************************************************************
* 文件名:main.c
* 描  述:
* 作  者:CLAY
* 版本號:v1.0.0
* 日  期: 2019年1月26日
* 備  注:TIM3_CH1-PA6, TIM3_CH2-PA7配置為輸入捕獲,
*         測量TIM4的CH1-PB6和PB7的頻率以及占空比
*******************************************************************************
*/

#include "config.h"
#include "led.h"
#include "key.h"
#include "timer.h"
#include "beep.h"
#include "lcd.h"
#include "stdio.h"
#include "usart.h"
#include "i2c.h"
#include "eeprom.h"
#include "PWMMode_Advance.h"
#include "PWM_Compare.h"
#include "PWM_Capture.h"


u8 string[20];

int main(void)
{
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	LEDInit();
	KeyInit();
	BeepInit();
	TIM2Init(2000, 72);//定時2ms
	
	TIM1_PWMInit(2000, 40, 80);//頻率2K CH2占空比40% CH3占空比80%
	TIM4_PWMCompare(2000, 1000, 40, 80);//CH1占空比2K 40% CH2 1K占空比80%
	
	TIM3_CaptureInit();
	
	while(1)
	{	
		KeyDriver();
		
		if(TIM3_CH1_CAPTURE_MODE == 3)
		{
			sprintf((char*)string,"ch1_fre:%d           ",1000000 / TIM3_CH1_CAPTURE_HL);
			LCD_DisplayStringLine(Line3, string);
			sprintf((char*)string,"ch1_duty:%d          ",TIM3_CH1_CAPTURE_H * 100/TIM3_CH1_CAPTURE_HL);
			LCD_DisplayStringLine(Line4, string);
			TIM3_CH1_CAPTURE_MODE = 0;
		}

		if(TIM3_CH2_CAPTURE_MODE == 3)
		{
			sprintf((char*)string,"ch2_fre:%d           ",1000000 / TIM3_CH2_CAPTURE_HL);
			LCD_DisplayStringLine(Line7, string);
			sprintf((char*)string,"ch2_duty:%d          ",TIM3_CH2_CAPTURE_H * 100/TIM3_CH2_CAPTURE_HL);
			LCD_DisplayStringLine(Line8, string);
			TIM3_CH2_CAPTURE_MODE = 0;
		}
	}
}

void KeyAction(int code)
{
	if(code == 1)//按下B1,切換燈狀態,蜂鳴器鳴叫0.1s
	{
		GPIOC->ODR ^= (1<<8);//PC8不斷取反
		GPIOD->ODR |= (1<<2);//PD2置1,使能573鎖存器
		GPIOD->ODR &= ~(1<<2);//PD2清0,關閉573鎖存器
		Beep(100);
	}
	else if(code == 2)
	{
		Beep(-1);
	}
	else if(code == 3)
	{
		Beep(0);
	}
	else if(code == 4)
	{
		
	}
}

PWM_Capture.c

#include "PWM_Capture.h"

u8 TIM3_CH1_CAPTURE_MODE = 0;
u32 TIM3_CH1_CAPTURE_H = 0, TIM3_CH1_CAPTURE_HL = 0;

u8 TIM3_CH2_CAPTURE_MODE = 0;
u32 TIM3_CH2_CAPTURE_H = 0, TIM3_CH2_CAPTURE_HL = 0;

u8 CAPTURE_MODE;

void TIM3_IOInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//***注意這里是APB2***
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA時鐘
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //TIM3通道1-PA6 TIM3通道2-PA7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//***輸入捕獲使用IO模式為上拉輸入或者浮空輸入
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//輸入就所謂輸出速度了,這句可省略。
	GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIO
}

void NVIC_TIM3Enable(void)
{
    NVIC_InitTypeDef NVIC_initstructure;

    NVIC_initstructure.NVIC_IRQChannel = TIM3_IRQn;           //選擇TIM4中斷通道
    NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE;           //使能中斷通道
    NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //設定搶占優先級為0
    NVIC_initstructure.NVIC_IRQChannelSubPriority = 0;        //設定響應優先級為0
    NVIC_Init(&NVIC_initstructure);
}

void TIM3Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	
	//***注意這里是APB1***
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能定時器3時鐘 
	TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //***設置為0xFFFF
	TIM_TimeBaseStructure.TIM_Prescaler = 72-1; //設置預分頻值
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鐘分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上計數模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化 TIM3
}

void TIM3_CaptureInit(void)
{
	TIM_ICInitTypeDef TIM_ICInitStructure;

	TIM3_IOInit();//TIM3通道1-PA6 TIM3通道2-PA7配置
	TIM3Init();//TIM3定時器配置
	NVIC_TIM3Enable();//中斷向量配置

	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//選擇通道
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿觸發
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//必須選擇指向TI寄存器
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不分頻
	TIM_ICInitStructure.TIM_ICFilter = 0;//不濾波
	TIM_ICInit(TIM3, &TIM_ICInitStructure);

	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICFilter = 0;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_ITConfig(TIM3, TIM_IT_CC1|TIM_IT_CC2, ENABLE);	
	TIM_Cmd(TIM3, ENABLE);
}



PWM_Capture.h

#ifndef _PWM_CAPTURE_H
#define _PWM_CAPTURE_H

#include "config.h"


void TIM3_CaptureInit(void);

extern u8 CAPTURE_MODE;

extern u8 TIM3_CH1_CAPTURE_MODE;
extern u32 TIM3_CH1_CAPTURE_H, TIM3_CH1_CAPTURE_HL;

extern u8 TIM3_CH2_CAPTURE_MODE;
extern u32 TIM3_CH2_CAPTURE_H, TIM3_CH2_CAPTURE_HL;

#endif

stm32f10x_it.c

void TIM2_IRQHandler(void)
{
	static u16 tmr500ms = 0;
	
	if(TIM_GetITStatus(TIM2, TIM_FLAG_Update))
	{
		TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
		tmr500ms++;
		KeyScan();
		BeepScan(2);//2ms掃描
		if(tmr500ms >= 250)
		{
			tmr500ms = 0;
			CAPTURE_MODE ^= 1;
		}
	}
}

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == 1)
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
		if(CAPTURE_MODE)
		{
			switch(TIM3_CH1_CAPTURE_MODE)
			{
				case 0: 
					TIM3_CH1_CAPTURE_H = 0;//
					TIM3_CH1_CAPTURE_HL = 0;
					TIM3_CH1_CAPTURE_MODE = 1;
					TIM_SetCounter(TIM3, 0);//計數值清0
					TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Falling);//設置為下降沿觸發
					break;
				case 1: 
					TIM3_CH1_CAPTURE_H = TIM_GetCounter(TIM3);//第一次獲取計數值
					TIM3_CH1_CAPTURE_MODE = 2;
					TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Rising);//設置為上升沿觸發
					break;
				case 2: 
					TIM3_CH1_CAPTURE_HL = TIM_GetCounter(TIM3);//第二次獲取計數值
					TIM3_CH1_CAPTURE_MODE = 3;
					TIM_OC1PolarityConfig( TIM3,TIM_ICPolarity_Rising);//設置為上升沿觸發
					break;
				default:
					break;
			}
		}
		else
		{
			TIM3_CH1_CAPTURE_MODE = 0;
		}
	}

	if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == 1)
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
		if(!CAPTURE_MODE)
		{
			switch(TIM3_CH2_CAPTURE_MODE)
			{
				case 0: 
					TIM3_CH2_CAPTURE_H = 0;
					TIM3_CH2_CAPTURE_HL = 0;
					TIM3_CH2_CAPTURE_MODE = 1;
					TIM_SetCounter(TIM3, 0);
					TIM_OC2PolarityConfig( TIM3,TIM_ICPolarity_Falling);
					break;
				case 1: 
					TIM3_CH2_CAPTURE_H = TIM_GetCounter(TIM3);
					TIM3_CH2_CAPTURE_MODE = 2;
					TIM_OC2PolarityConfig( TIM3,TIM_ICPolarity_Rising);
					break;
				case 2: 
					TIM3_CH2_CAPTURE_HL = TIM_GetCounter(TIM3);
					TIM3_CH2_CAPTURE_MODE = 3;
					TIM_OC2PolarityConfig( TIM3,TIM_ICPolarity_Rising);
					break;
				default:
					break;
			}
		}
		else
		{
			TIM3_CH2_CAPTURE_MODE = 0;
		}
	}

}

二、需要注意的地方

1、實驗結果

2、由于我是直接用之前的工程,之前TIM3做了通用定時器的PWM模式輸出實驗,而現在要配置為輸入捕獲,兩個同時存在會出現如下錯誤:

所以要刪除pwmmode相關文件,包括以下幾個:

3、程序中的變量釋義

TIM3_CH1_CAPTURE_MODE 用來記錄當前捕獲在哪個位置 TIM3_CH1_CAPTURE_H 用來記錄第一次捕獲的時間 TIM3_CH1_CAPTURE_HL 用來記錄第二次捕獲的時間

4、CAPTURE_MODE 的優秀所在

兩個通道肯定不能同時進行捕獲,首先兩者同時捕獲,同時記錄這個無所謂,關鍵是它們還都涉及計算。計算最怕被中斷打斷,這樣可能導致結果不正確。這里目前有兩種解決方案,一種是分時復用,就像上面程序中寫的那樣,另外一種解決辦法就像我們51操作步進電機計算節拍或者就像控制DHT11時序一樣,開關總中斷,這個方法稍后再做調試,會一并掛上來。

5、中斷函數里總的處理思想

當TIM3_CH1_CAPTURE_MODE=0時,如果發生了中斷,那么就代表我們捕獲到了上升沿,當前在上面簡圖的A點,我們把定時器計數值清0,讓定時器重新計數,同時還要把觸發方式設置為下降沿觸發。

當TIM3_CH1_CAPTURE_MODE=1時候,發生了中斷,那么就代表我們捕獲到了下降沿,當前的位置在上面簡圖的B點,我們獲取一次定時器的計數值,同時還得把我們觸發方式設置為上升沿觸發。

當TIM3_CH1_CAPTURE_MODE=2時候,發生中斷,那么就代表我們一個周期已經捕獲完畢了,當前位置在上面簡圖的C點,我們再獲取一次定時器的計數值,隨后就可以根據我們兩次獲取的計數值,算出我們方波的頻率和周期。

當TIM3_CH1_CAPTURE_MODE=3時,就意味著我們可以開始計算周期和頻率,當我們處理好數據后,我們就可以把TIM3_CH1_CAPTURE_MODE清0,準備開始下一次捕獲。

然后在主函數中,進行TIM3_CH1_CAPTURE_MODE狀態判斷,進而計算出占空比和頻率的值,然后顯示到LCD上,隨后再開啟下一次捕獲。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 150
收藏 149
關注 431
成為作者 賺取收益
全部留言
0/200
  • dy-i2UfRuvP 2021-05-19 13:17
    大開眼界,真是好文
    回復
  • dy-iipPZRPN 2021-05-13 22:39
    圍觀學習
    回復
  • dy-3EbVR6Ei 2021-05-13 22:27
    對我很有幫助
    回復
  • dy-Xq2JxpfN 2021-05-13 22:12
    請教一下
    回復
  • dy-9g42stbW 2021-05-13 21:55
    對我很有幫助
    回復
  • dy-mLj7kl5v 2021-05-13 20:31
    什么時候更新
    回復
  • dy-apcih3c1 2021-05-13 20:12
    什么時候更新
    回復
  • dy-k78ZHtFD 2021-05-13 20:02
    期待繼續
    回復
  • dy-nAWdnPGS 2021-05-13 18:50
    大開眼界,真是好文
    回復
  • dy-prSX6RBY 2021-05-13 18:38
    不亞于看了一篇高質量論文
    回復
  • dy-jqGVYqsF 2021-05-13 16:05
    請教一下
    回復
  • dy-VIQ9auhf 2021-05-13 14:54
    學習了
    回復
  • dy-7mura2gg 2021-05-13 14:44
    比論文強一萬倍
    回復
  • dy-YN3DYTeH 2021-05-13 14:34
    講的真好!
    回復
  • dy-9hjGevyn 2021-05-13 13:33
    大開眼界,真是好文
    回復
  • dy-H1WY5jXH 2021-05-13 13:17
    精彩,很多東西還沒接觸到
    回復
  • dy-wVQjSHHX 2021-05-13 12:59
    比論文強一萬倍
    回復
  • dy-88VlYaFf 2021-05-12 15:35
    期待繼續
    回復
  • dy-9QTV6UZW 2021-05-12 15:23
    感謝分享
    回復
  • dy-WYS5BCmB 2021-05-12 15:10
    不亞于看了一篇高質量論文
    回復
主站蜘蛛池模板: 99在线在线视频免费视频观看 | 精品首页 | 亚洲第一区无码专区 | 欧美日韩国产限制 | 国产成人久久婷婷精品流白浆 | 草久视频在线 | 乱码一区二区三区四区 | 久久超乳爆乳中文字幕 | aa视频免费看 | 亚洲国产影院av久久久久 | 国产91精品亚洲一区二区三区 | 就去色播| 亚州成人在线观看 | 久久青青草原一区二区 | 久久久精品国产免费观看一区二区 | 熟妇人妻AV中文字幕老熟妇 | 欧美精品一国产成人综合久久 | 亚洲高清无吗 | 无码免费一区二区三区免费播放 | 亚洲影视网 | 在线观看色网 | 99久久无码一区人妻A片红豆 | 国产在线啪 | 色欲网天天无码av | 国产A级护士毛片 | 男女视频免费看 | 久久久久久久久免费 | 色姑娘久 | 狂猛欧美激情性xxxx在线观看 | 99激情网 | 亚洲韩国精品无码一区二区三区 | 一性一交一伦一色一情人 | 日韩国产一级片 | 风韵丰满熟妇啪啪区老老熟女百度 | 免费在线观看一区二区三区 | 午夜福利精品导航凹凸 | 国产免费一区二区三区在线观看 | 污污网站国产精品白丝袜 | 67194熟妇在线永久免费观看 | 男女性高爱潮免费网站 | 人人妻人人澡人人爽人人精品AV |