【STM32】TIM定時器編碼器

1?編碼器接口簡介

Encoder Interface 編碼器接口

編碼器接口可接收增量(正交)編碼器的信號,根據編碼器旋轉產生的正交信號脈沖,自動控制CNT自增或自減,從而指示編碼器的位置、旋轉方向和旋轉速度

接收正交信號,自動執行CNT自增或者自減,編碼器接口相當于帶有方向控制的外部時鐘,同時控制著CNT的計數時鐘和計數方向。每隔一段時間去取一次CNT的值,再把CNT清零,每次取出來的值就表示編碼器的速度。(測頻法)

每個高級定時器和通用定時器都擁有1個編碼器接口

兩個輸入引腳借用了輸入捕獲的通道1和通道2(CH1和CH2)

1.1?正交編碼器

正交編碼器一般可以測量位置或者帶有方向的速度值

旋轉編碼器:用來測量位置、速度或旋轉方向的裝置,當其旋轉軸旋轉時,其輸出端可以輸出與旋轉速度和方向對應的方波信號,讀取方波信號的頻率和相位信息即可得知旋轉軸的速度和方向

類型:機械觸點式/霍爾傳感器式/光柵式

?

方波頻率代表速度。正轉時A相提前B相90°;反轉時A相滯后B相90°

首先把A\相和B相的所有邊沿作為計數器的計數時鐘,出現邊沿信號時就計數器自增或者自減;計數的方向由另一相的狀態來確定。當出現某個邊沿時,判斷另一相高低電平,如果另一相的狀態出現在上面這個表中,那就是正轉,計數自增;否則就是反轉,計數自減。這樣就可以實現編碼器接口的功能了。

編碼器接口有兩個輸入端,分別接到編碼器的A相和B相,所以編碼器的輸入引腳就是定時器的CH1和CH2引腳。編碼器的輸出部分相當于從模式的控制器了,控制CNT的計數時鐘和計數方向。計數器的自增和自減受編碼器控制。

1.2?編碼器接口基本結構

很清晰

1.3?工作模式

這里TI1FP1和TI2FP2接的就是AB相。計數和前面一樣。

正轉向上計數,反轉向下計數。

1.4?實例圖

均不反向,使用TI1和TI2都計數

很清晰。

TI1反向,TI2不反向。極性的變化對計數的影響。

這里的極性選擇就是高低電平的極性選擇了。如果選擇上升沿的參數,就是信號直通過來,高低電平極性不反轉;如果選擇下降沿的參數,就是信號通過非門,高低電平反轉。

很清晰。

手冊

2? 編碼器接口測速

2.1?接線圖

引腳定義

計劃用TIM3的通道1和通道2

2.2?模塊封裝

按這個配置

庫函數

// 定時器編碼器接口配置
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);

版本一:Encoder.c

#include "stm32f10x.h"                  // Device header// 編碼器接口初始化函數
void EnCoder_Init(void)
{// 1開啟時鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 2配置GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;         		// 上拉輸入模式GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);// 3配置時基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;                    	// PSC預分頻器的值,不分頻TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;                     	// ARR自動重裝器的值 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;      	// 向上計數,沒有用TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;			// 不分頻TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;                	// 重復計數器的值TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);// 4配置輸入捕獲單元(只有極性和濾波器兩個參數有用)TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICStructInit(&TIM_ICInitStruct);                               // 結構體初始化TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;					   // 通道1TIM_ICInitStruct.TIM_ICFilter = 0xF;							   // 濾波器
//	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;		   // 和后面重復
//	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;       // 無作用
//	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;                 // 無作用TIM_ICInit(TIM3, &TIM_ICInitStruct);TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;TIM_ICInitStruct.TIM_ICFilter = 0xF;//	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;	   // 和后面重復TIM_ICInit(TIM3, &TIM_ICInitStruct);// 5配置編碼器接口模式// TIM_ICPolarity_Rising這個通道不反向,TIM_ICPolarity_Falling這個通道反向// 后兩個參數相反就是方向相反TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);// 6啟動定時器TIM_Cmd(TIM3, ENABLE);
}// 獲取CNT的值
int16_t Encoder_Get(void)
{return TIM_GetCounter(TIM3);
}

版本二:Encoder.c

#include "stm32f10x.h"                  // Device header// 編碼器接口初始化函數
void EnCoder_Init(void)
{// 1開啟時鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 2配置GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;         		// 上拉輸入模式GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);// 3配置時基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;                    	// PSC預分頻器的值,不分頻TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;                     	// ARR自動重裝器的值 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;      	// 向上計數,沒有用TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;			// 不分頻TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;                	// 重復計數器的值TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);// 4配置輸入捕獲單元(只有極性和濾波器兩個參數有用)TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICStructInit(&TIM_ICInitStruct);                               // 結構體初始化TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;					   // 通道1TIM_ICInitStruct.TIM_ICFilter = 0xF;							   // 濾波器
//	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;		   // 和后面重復
//	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;       // 無作用
//	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;                 // 無作用TIM_ICInit(TIM3, &TIM_ICInitStruct);TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;TIM_ICInitStruct.TIM_ICFilter = 0xF;//	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;	   // 和后面重復TIM_ICInit(TIM3, &TIM_ICInitStruct);// 5配置編碼器接口模式// TIM_ICPolarity_Rising這個通道不反向,TIM_ICPolarity_Falling這個通道反向// 后兩個參數相反就是方向相反TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);// 6啟動定時器TIM_Cmd(TIM3, ENABLE);
}// 獲取CNT的值
int16_t Encoder_Get(void)
{
//    return TIM_GetCounter(TIM3);// 讀取cnt,把cnt清零的邏輯int16_t temp = TIM_GetCounter(TIM3);TIM_SetCounter(TIM3, 0);return temp;
}

2.3?主函數

版本一:主函數

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "EnCoder.h"int main()
{OLED_Init();								// 初始化OLEDEnCoder_Init();
//	Timer_Init();								// 初始化定時器OLED_ShowString(1, 1, "CNT:");   			// 顯示字符串while (1){OLED_ShowNum(1, 5, Encoder_Get(), 5);    // 顯示CNT計數器}
}

版本二:主函數

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "EnCoder.h"int16_t speed;int main()
{OLED_Init();								// 初始化OLEDEnCoder_Init();Timer_Init();								// 初始化定時器OLED_ShowString(1, 1, "speed:");   			// 顯示字符串while (1){OLED_ShowSignedNum(1, 7, speed, 5);    		 // 顯示CNT計數器}
}// 中斷函數
void TIM2_IRQHandler(void)
{// 檢測中斷標志位,確保是設置的中斷源觸發的這個函數if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){// 中斷處理speed = Encoder_Get();// 清除中斷標志TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/211530.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/211530.shtml
英文地址,請注明出處:http://en.pswp.cn/news/211530.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

黑豹程序員-EasyExcel實現導出

需求 將業務數據導出到excel中,老牌的可以選擇POI,也有個新的選擇EasyExcel。 有個小坑,客戶要求樣式比較美觀,數字列要求千位符,保留2位小數。 可以用代碼實現但非常繁瑣,用模板就特別方便,模…

C++優秀串口庫

serial::Serial Class Reference #include <serial.h> Data Structures class ScopedReadLockclass ScopedWriteLock Public Member Functions公有成員方法&#xff08;編程用的都在這里了&#xff0c;那些私有的如果不開源一般跟我們沒有關系了&#xff09; Serial …

用chatGPT開發項目:我想的無人的智慧樹網站 流量之神 利用人工智能的算法將人吸引住 GPT4是不是越來越難用了,問一下就要證明一下自己是不是人類

廣度發散&#xff1a;讓AI給出時代或今日或你關注的熱點事件 比如采集新聞頭條&#xff0c;根據內容或標題&#xff0c;以不同的角度&#xff0c;或各種人群的角色&#xff0c;生成50篇簡短的文章。一下就能占傳統的搜索引擎。這是AI最擅長的【千人千面&#xff0c;海量生成】…

【中國海洋大學】操作系統隨堂測試6整理

1. IO系統的層次機構包括&#xff1a;IO硬件、中斷處理程序、&#xff08;&#xff09;程序、設備獨立性軟件、用戶層軟件。 答&#xff1a;設備驅動 2. IO設備和控制器之間的接口包括三種類型的信號&#xff1a;數據信號線、控制信號線和&#xff08;&#xff09;&#xff1…

qt反射基礎

最近研究了一下QT的反射機制&#xff0c; Qt的元對象系統除了提供信號/槽機制的特性之外&#xff0c;它還提供了以下特性: QObject::metaObject() 返回關聯的元對象 QMetaObject::className() 在運行時狀態下返回類名 QObject::inherits() 判斷類的繼承關系 QObject::tr()&…

鴻蒙開發之封裝優化

面向對象開發離不開封裝&#xff0c;將重復的可以復用的代碼封裝起來&#xff0c;提高開發效率。 基于之前的List&#xff0c;對代碼進行封裝。 1、抽取component 將List的頭部抽離出來作為一個新的component。可以創建一個新的ArkTS文件&#xff0c;寫我們的頭部代碼 為了…

代理模式:解析對象間的間接訪問與控制

目錄 引言 理解代理模式 不同類型的代理模式 代理模式的應用場景 代理模式的優缺點 優點 缺點 實際案例&#xff1a;Java中的代理模式應用 結語 引言 代理模式是軟件設計模式中的一種結構型模式&#xff0c;旨在為其他對象提供一種代理以控制對這個對象的訪問。它允許你…

消息隊列使用指南

介紹 消息隊列是一種常用的應用程序間通信方法&#xff0c;可以用來在不同應用程序或組件之間傳遞數據或消息。消息隊列就像一個緩沖區&#xff0c;接收來自發送方的消息&#xff0c;并存儲在隊列中&#xff0c;等待接收方從隊列中取出并處理。 在分布式系統中&#xff0c;消…

死鎖問題,4個必要條件+避免死鎖

目錄 引入 死鎖 概念 示例 多把鎖 單鎖 4個必要條件 用途 引入 我們用加鎖的方式保證了多個線程訪問臨界資源時,不會出現數據紊亂的問題 但是,鎖的引入,會導致出現其他的問題 死鎖 概念 在多線程或多進程的并發環境中&#xff0c;兩個或多個進程或線程被永久阻塞&…

esxi全稱“VMware ESXi

esxi全稱“VMware ESXi”&#xff0c;是可直接安裝在物理服務器上的強大的裸機管理系統&#xff0c;是一款虛擬軟件&#xff1b;ESXi本身可以看做一個操作系統&#xff0c;采用Linux內核&#xff0c;安裝方式為裸金屬方式&#xff0c;可直接安裝在物理服務器上&#xff0c;不需…

數據結構算法-希爾排序算法

引言 在一個普通的下午&#xff0c;小明和小森決定一起玩“誰是老板”的撲克牌游戲。這次他們玩的可不僅僅是娛樂&#xff0c;更是要用撲克牌來決定誰是真正的“大老板”。 然而&#xff0c;小明的牌就像剛從亂麻中取出來的那樣&#xff0c;毫無頭緒。小森的牌也像是被小丑擲…

Agent學習筆記

背景&#xff1a;LLM → \to → Agent ChatGPT為代表的大語言模型就不用過多的介紹了&#xff0c;ChatGPT很強大&#xff0c;但是也有做不到的東西。例如&#xff1a; 實時查詢問題&#xff1a;實時的天氣&#xff0c;地理位置&#xff0c;最新新聞報道&#xff0c;現實世界…

十年婚姻·總結八

十年婚姻總結八 女人一生的合伙人不能只是帥哥哥 女人一生的合伙人不能只是帥哥哥 浪漫的本質還是你的籌碼。 比如你送男人5萬的手表&#xff0c;但你沒什么其他籌碼&#xff08;皮膚粗糙蠟黃、沒人脈金錢資源、長的胖&#xff09;。 那個男人會覺得你胡鬧&#xff0c;你送的…

分類預測 | SSA-HKELM-Adaboost麻雀算法優化混合核極限學習機的數據分類預測

分類預測 | SSA-HKELM-Adaboost麻雀算法優化混合核極限學習機的數據分類預測 目錄 分類預測 | SSA-HKELM-Adaboost麻雀算法優化混合核極限學習機的數據分類預測分類效果基本描述程序設計參考資料 分類效果 基本描述 1.SSA-HKELM-Adaboost麻雀算法優化混合核極限學習機的數據分類…

引用文獻算作重復率么【一文讀懂】

大家好&#xff0c;今天來聊聊引用文獻算作重復率么&#xff0c;希望能給大家提供一點參考。 以下是針對論文重復率高的情況&#xff0c;提供一些修改建議和技巧&#xff1a; 引用文獻算作重復率么 在學術研究和論文撰寫過程中&#xff0c;引用文獻是不可或缺的一部分小發貓偽…

shell學習1——txt文件備份,文件名加個年月日的后綴,如test.txt對于備份文件為test.txt_20231205

跟B站Up主學習shell腳本——阿銘linux 3461576172505894 需求 txt文件備份&#xff0c;文件名加個年月日的后綴&#xff0c;如test.txt對于備份文件為test.txt_20231205 代碼 #!/bin/bash ##定義后綴變量 suffixdate %Y%m%d##找到/test/目錄下的txt文件 for f in find /tes…

ubuntu源配置文件/etc/apt/sources.list不存在

若使用命令sudo apt-get update報錯&#xff1a;apt-get:找不到命令&#xff0c;八成是源配置文件/etc/apt/sources.list不存在。但是一般來說不會不存在&#xff0c;若真的不小心刪除的話&#xff0c;我們也可以進行恢復。 首先創建/etc/apt/sources.list文件&#xff0c;然后…

安卓與串口通信-如何區分連接的設備?

前言與背景 一般來說&#xff0c;不管是在什么平臺上需要與外接硬件交互&#xff0c;第一件事都是應該能夠正確的識別出目標硬件。 例如在 Windows 上&#xff0c;當一個新的外設設備被插入到我們的電腦時&#xff0c;系統會通過 Hardware IDs 、Compatible IDs 來確定連接的…

看圖學源碼之 Atomic 類源碼淺析二(cas + 分治思想的原子累加器)

原子累加器 相較于上一節看圖學源碼 之 Atomic 類源碼淺析一&#xff08;cas 自旋操作的 AtomicXXX原子類&#xff09;說的的原子類&#xff0c;原子累加器的效率會更高 XXXXAdder 和 XXXAccumulator 區別就是 Adder只有add 方法&#xff0c;Accumulator是可以進行自定義運算方…

ufw常用命令解析

命令 舉例 解釋 ufw enable — 啟用防火墻 ufw disable — 禁用防火墻 ufw status — 查看防火墻狀態與規則 ufw default ARG sudo ufw default allow sudo ufw default deny 將默認策略設置為允許所有未明確規定的流量 將默認策略設置為拒絕所有未明確規定的流量…