STM32學習筆記6-TIM-2輸出比較功能

第二部分,定時器的輸出比較功能

OC(Output Compare)輸出比較

輸出比較可以通過比較CNT與CCR寄存器值的關系,來對輸出電平進行置1、置0或翻轉的操作,用于輸出一定頻率和占空比的PWM波形

每個高級定時器和通用定時器都擁有4個輸出比較通道

高級定時器的前3個通道額外擁有死區生成和互補輸出的功能

IC:輸入捕獲、CC:表示輸入捕獲和輸出比較的單元、CCR:捕獲比較寄存器

CCR是輸入捕獲和輸出捕獲比較共用的,會根據輸出和輸入比較的情況,轉換對于寄存器功能;在輸出比較中,電路會比較CNT和CCR的值,CNT自增,當CNT大于CCR、等于CCR和小于CCR時,會輸出對于的置0或1,從而輸出一個電平不斷跳變的PWN波形;共用一個CNT計數器

PWM(Pulse Width Modulation)脈沖寬度調制

最常見的用途是產生PWM波形,用于驅動電機等設備

在具有慣性的系統中,可以通過對一系列脈沖的寬度進行調制,來等效地獲得所需要的模擬參量,常應用于電機控速等領域,是數字信號

PWM參數:

???? 頻率 = 1 / TS??????????? 占空比 = TON / TS?????????? 分辨率 = 占空比變化步距

Ts圖下:代表一個高低電平變換周期的時間

Ton:高電平的時間、Toff? 同理

?

頻率越快,等效模擬的信號就越平穩,性能的開銷就大

在今天的實驗中我們實現的LED呼吸燈中,正常來說數字信號只有0和1,所以只會實現亮和滅的情況,但是通過PWM波形用數字信號來輸出一段模擬信號就可以實現呼吸燈:讓LED燈不斷點亮、熄滅、點亮、熄滅,當點亮和熄滅的頻率足夠大時,LED就不會閃爍了,而是呈現出一個中等亮度,這時進行調控點亮和熄滅的時間比例,就能呈現出不同亮度;(唯快不破)

輸出比較通道(通用)

整體電路所在的方位? ? ? ?

CCR與CNT比較,輸出數字信號(0和1),輸出控制器會改變它輸出OC1PRE的高低電平;REF信號可以進入主模式控制器,這樣可以將REF映射到TRGO輸出上去;主要是走下一路,達到極性選擇,通過極性選擇到輸出使能電路,選擇要不要輸出,輸出至OC1引腳(引腳對應表)

極性選擇 :給這個寄存器寫0,信號就會往上走,信號電平不翻轉;寫1,信號會往下走,信號會通過一個非門取反,此時輸出的信號就是輸入信號高低電平反轉的信號

REF信號:實際就是指這里信號的高低電平——參考信號

輸出比較的8種模式

輸出控制器里的執行邏輯,靈活地控制REF的輸出;通過一個寄存器來進行配置

作用:

凍結:在輸出PWM波形時,想要進行停止,就可以設置此,此時就暫停了輸出,并且高低電平也維持在暫停時的樣子

匹配時置無效電平&匹配時置有效電平:一般是高級定時器的說法,與關斷、剎車燈功能一起的,有效電平就是高電平,無效電平則反之,一次性的,不適合輸出連續變化的波形。

匹配時電平翻轉:可以輸出一個頻率可調,占空比始終50%的PWM波形:比如當CCR設置為0時,CNT每次更新清0時,就會產生一次CNT=CCR的事件,從而導致輸出電平翻轉一次,每更新兩次,輸出為一個周期,同時高低電平時間始終相等,占空比始終為50%;則關系是輸出頻率=更新頻率/2

強制為無效電平&強制為有效電平:與凍結差不多

PWM模式1& PWM模式2:用于輸出頻率和占空比都可調的PWM波形,主要使用

PWM的基本結構:

紅色代表:CCR

藍色代表:CNT

黃色代表:ARR

下面的圖表示輸出的PWM波形:

藍色從0開始自增,直到與黃色相同時,出現中斷,更新清0繼續自增;

紅色設置為30,因為輸出控制器設置的模式是,當CNT<CCR時,為高電平;所以根據藍色與黃色不斷的更新,CCR會輸出不同的REF信號,同時不僅可以調整紅色設置的值,并且占空比也受CCR的調控。


參數計算

  • PWM頻率:??? Freq = CK_PSC / (PSC + 1) / (ARR + 1)
  • PWM占空比:?????? Duty = CCR / (ARR + 1)
  • PWM分辨率:?????? Reso = 1 / (ARR + 1)

CK_PSC:輸入定時器的總頻率;PSC=預分頻器的分頻數

占空比變化越細,越好

輸出比較通道(高級定時器)

與通用定時器的區別:

當外部設備是一個大功率開關管(Mos管),兩邊開關分別連接著OC1和OC1N,假設是高電平導通,電平斷開;兩個開關中間對應輸出;如果上管導通,下管斷開,則是高電平,反之;但是如果兩邊都導通,則會短路或者兩邊都斷開,則是高阻態;這就是推挽電路;如果有兩個這樣的電路相連接,則是H橋電路,可控制直流電路正反轉了;如果有三個這樣的電路,就可以用于驅動三相無刷電機;

回歸內部,如果在上管關斷的瞬間,下管立刻就打開,那可能會上管還沒完全關斷,下管已經導通,出現兩邊同時導通的現象,從而功率損耗,所以避免這個問題就設置了死區發生器電路,會在關閉的時候延遲一段時間,再導通;

外部設備:

舵機簡介

  • 舵機是一種根據輸入PWM信號占空比來控制輸出角度的裝置
  • 輸入PWM信號要求:周期為20ms(50Hz),高電平寬度為0.5ms~2.5ms

?

邏輯:PWM信號輸入到控制板,給控制板一個指定的目標角度,然后這個電位器檢測輸出軸的當前角度,如果大于目標角度,電機會反轉,反之,最終使輸出軸固定在指定角度。

輸出軸角度:時間是指此輸入信號的電平變化到下一個電平變化的時間

這里是PWM當作一個通信協議

硬件電路:

引腳定義圖

直流電機及驅動簡介

  • 直流電機是一種將電能轉換為機械能的裝置,有兩個電極,當電極正接時,電機正轉,當電極反接時,電機反轉
  • 直流電機屬于大功率器件,GPIO口無法直接驅動,需要配合電機驅動電路來操作
  • TB6612是一款雙路H橋型的直流電機驅動芯片,可以驅動兩個直流電機并且控制其轉速和方向

硬件電路:

?

接線圖

6-3 PWM驅動LED呼吸燈

這里我們LED正極接入A0引腳,負極在GND的方法,這樣是高電平點亮,正極性驅動;占空比越高越亮;


  1. RCC開啟時鐘,把TIM外設和GPIO外設的時鐘打開
  2. 配置時基單元,包括時鐘源選擇
  3. 配置輸出比較單元:包括CCR的值、輸出比較模式、極性選擇、輸出使能等由結構體統一配置
  4. 配置GPIO,把PWM對于的GPIO口,初始化為復用推挽輸出的配置
  5. 運行控制

相關庫函數:

//配置輸出比較模塊,一個函數配置一個單元,一共有四個單元,不同的通道對不同的GPIO口,對應關系:

得知:TIM2的ETR引腳和CH1通道1的引腳復用在PA0引腳上,所以我們要輸出TIM2的OC1通道輸出PWM,那就只能在PA0的引腳上輸出;如果想跳出這個映射,則需要看這重定義功能表里是否對應接口映射,再通過配置AFIO來完成。

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);//用來輸出比較結構體賦一個默認值

//小功能和運行參數

//配置強制輸出模式,就是設置100%高電平一樣

void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

//四個函數用來配置CCR寄存器的預裝功能的,就是緩存寄存器

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

//用來配置快速使能的

void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

//外部事件時清除REF信號

void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

//用來單獨設置輸出比較的極性,帶N的就是高級定時器里互補通道的配置

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

//單獨修改輸出使能參數的

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);

void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

//選擇輸出比較模式

void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

//用來單獨更改CCR寄存器值的函數,更改占空比

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);

void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);

void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);

void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

//僅高級定時器使用,在使用高級定時器輸出PWM時,需要調用這個函數使能輸出

void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

示波器:1KHz,CCR為50,此時占空比為50%

1KHz,CCR為10,占空比減少至10%,燈變暗

1KHz,CCR為90,占空比增加至90%,燈變亮

main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
uint8_t i;
int main(void){OLED_Init();PWM_Init();while(1){for(i=0;i<=100;i++){PWM_set(i);Delay_ms(50);}for(i=0;i<=100;i++){PWM_set(100-i);Delay_ms(50);}}
}PWM.c
#include "stm32f10x.h"                  // Device header
void PWM_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  //開啟APB1的時鐘函數,TIM2在APB1總線中//選擇時基單元TIM_InternalClockConfig(TIM2);//系統默認是內部時鐘,不寫也可以//配置時基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //給輸入的濾波器一個采樣頻率TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//計數方式TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARR自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//PSC預分配器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重復計數器的值,我們用的通用寄存器,所以直接寫0就好了TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_IT_Update);//初始化輸出比較單元:頻率1kHz,占空比為50%的PWM波形//TIM_OCInitStructure函數有一部分是高級定時器里的,要么就把全部成員拉出來配置,要么就用TIM_OCStructInit先賦一個初始值0TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//8種輸出比較模式TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//輸出比較極性TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//輸出使能//因此通過觀察得知,我們需要完成的呼吸燈的變化效果就與CCR的值息息相關,TIM_SetCompare1單獨更改CCR值的函數就有用了TIM_OCInitStructure.TIM_Pulse=0;//就是CCR的值TIM_OC1Init(TIM2, &TIM_OCInitStructure);//現在把TIM2上的OC1通道上就可以輸出PWM波形,這個波形是需要借助GPIO口才能輸出,郵引腳定義表得知我們鎖定在PA0引腳上/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出,因為普通的推挽輸出,引腳的控制權是來自于輸出數據寄存器的,那我們這時想讓的是定時器來控制引腳,則需要使用復用推挽輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);						//啟動定時器TIM_Cmd(TIM2, ENABLE);
}
void PWM_set(uint16_t compare){TIM_SetCompare1(TIM2,compare);
}

重定義映射:

開啟AFIO時鐘

使用引腳重映射配置GPIO_PinRemapConfig

與TIM2的映射關系一共4個,我們要把PA0映射到PA5,就使用2或則和4的關系

APIO的函數參數

注意PA15上電后默認復用調試端口JTDI,需要把它的默認給取消了才能正常使用

繼續使用GPIO_PinRemapConfig,參數

三個參數:就是來解除復用的:
GPIO_Remap_SWJ_NoJTRST? :解除JTRST引腳的復用

GPIO_Remap_SWJ_JTAGDisable? :解除JTAG調試端口的復用

GPIO_Remap_SWJ_Disable? :把SWD和JTAG的調試端口全部解除,此參數需要考慮使用,因為如果使用了,那STLInk就沒有輸出端口了,需要額外去配置

PWM.c
#include "stm32f10x.h"                  // Device header
void PWM_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  //開啟APB1的時鐘函數,TIM2在APB1總線中//用引腳重映射,所以需要考慮使用AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_FullRemap_TIM2,ENABLE);//PA0到PA15//注意PA15也有自己的默認,需要把它的默認給取消了才能正常使用GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//選擇時基單元TIM_InternalClockConfig(TIM2);//系統默認是內部時鐘,不寫也可以//配置時基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //給輸入的濾波器一個采樣頻率TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//計數方式TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARR自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//PSC預分配器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重復計數器的值,我們用的通用寄存器,所以直接寫0就好了TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_IT_Update);//初始化輸出比較單元:頻率1kHz,占空比為50%的PWM波形//TIM_OCInitStructure函數有一部分是高級定時器里的,要么就把全部成員拉出來配置,要么就用TIM_OCStructInit先賦一個初始值0TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//8種輸出比較模式TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//輸出比較極性TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//輸出使能//因此通過觀察得知,我們需要完成的呼吸燈的變化效果就與CCR的值息息相關,TIM_SetCompare1單獨更改CCR值的函數就有用了TIM_OCInitStructure.TIM_Pulse=0;//就是CCR的值TIM_OC1Init(TIM2, &TIM_OCInitStructure);//現在把TIM2上的OC1通道上就可以輸出PWM波形,這個波形是需要借助GPIO口才能輸出,郵引腳定義表得知我們鎖定在PA0引腳上/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出,因為普通的推挽輸出,引腳的控制權是來自于輸出數據寄存器的,那我們這時想讓的是定時器來控制引腳,則需要使用復用推挽輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//重映射GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);						//啟動定時器TIM_Cmd(TIM2, ENABLE);
}
void PWM_set(uint16_t compare){TIM_SetCompare1(TIM2,compare);
}

6-4 PWM驅動舵機

CCR為500,對應轉0°

修改參數:

CCR為2500,對應180°;

修改參數:

CCR為1500,對應90°;

main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "key.h"
#include "PWM.h"uint8_t Keynum=0;//按鍵鍵碼
float Angle;//角度變量
int main(void){OLED_Init();PWM_Init();
//	//PWM_set(500);//此時時間為0.5ms,處于不動的狀態//PWM_set(2500);//此時時間為2.5ms,轉180°
//	PWM_set(1500);//此時時間為1.5ms,轉90°Key_Init();Servo_Init();OLED_ShowString(1,1,"Angle:");while(1){Keynum=Key_GetNum();if(Keynum==1){Angle+=30;if(Angle>180){Angle=0;}}Servo_Setangle(Angle);OLED_ShowNum(1,7,Angle,3);}
}
Servo.c
#include "stm32f10x.h"                  // Device header
#include "PWM.h"
//給舵機一個模塊,用來實現目標功能void Servo_Init(void){PWM_Init();
}void Servo_Setangle(float Angle){PWM_set(Angle/180*2000+500);
}
PWM.c
#include "stm32f10x.h"                  // Device header
void PWM_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  //開啟APB1的時鐘函數,TIM2在APB1總線中/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//開啟GPIOA的時鐘,設置舵機PWM的接口/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出,因為普通的推挽輸出,引腳的控制權是來自于輸出數據寄存器的,那我們這時想讓的是定時器來控制引腳,則需要使用復用推挽輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);		//選擇時基單元TIM_InternalClockConfig(TIM2);//系統默認是內部時鐘,不寫也可以//配置時基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //給輸入的濾波器一個采樣頻率TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//計數方式TIM_TimeBaseInitStructure.TIM_Period=20000-1;//ARR自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//PSC預分配器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重復計數器的值,我們用的通用寄存器,所以直接寫0就好了TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_IT_Update);//初始化輸出比較單元:舵機要求的周期是20ms,則頻率為1/20ms=50Hz,要求高電平時間是0.5-2.5ms//PWM頻率:	Freq = CK_PSC / (PSC + 1) / (ARR + 1)//PWM占空比:	Duty = CCR / (ARR + 1)//PWM分辨率:	Reso = 1 / (ARR + 1)//TIM_OCInitStructure函數有一部分是高級定時器里的,要么就把全部成員拉出來配置,要么就用TIM_OCStructInit先賦一個初始值0TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//8種輸出比較模式TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//輸出比較極性TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//輸出使能//因此通過觀察得知,我們需要完成的呼吸燈的變化效果就與CCR的值息息相關,TIM_SetCompare1單獨更改CCR值的函數就有用了TIM_OCInitStructure.TIM_Pulse=0;//就是CCR的值TIM_OC2Init(TIM2, &TIM_OCInitStructure);  //通道修改為2,同一個定時器不同的特性:因為不同的通道相位,產生PWM都是一樣的,但是CCR是可以單獨設置的//啟動定時器TIM_Cmd(TIM2, ENABLE);
}
void PWM_set(uint16_t compare){TIM_SetCompare2(TIM2,compare); //修改通道2的CCR
}

6-5 PWM驅動直流電機

main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "Key.h"
uint8_t Keynum;
int8_t Speed;
int main(void){OLED_Init();Key_Init();Motor_Init();//Motor_Speed(50);//正轉
//	Motor_Speed(-50);//反轉OLED_ShowString(1,1,"Speed:");while(1){Keynum=Key_GetNum();if(Keynum==1){Speed +=20;if(Speed>100){Speed=-100;}}Motor_Speed(Speed);OLED_ShowSignedNum(1,7,Speed,3);}
}Motor.c
#include "stm32f10x.h"                  // Device header
#include "PWM.h"
void Motor_Init(void){PWM_Init();//需要額外去控制電機的方向控制的兩個腳/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);						//將PA1和PA2引腳初始化為推挽輸出//默認就是低電平,所以不需要對輸出電平進行設置就可以亮燈}void Motor_Speed(int8_t Speed){if(Speed>=0){//設置方向一個為高,一個為低GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_ResetBits(GPIOA,GPIO_Pin_5);PWM_set(Speed);}else{GPIO_ResetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOA,GPIO_Pin_5);PWM_set(-Speed);}
}

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

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

相關文章

MATLAB核心技巧:從入門到精通

一 1.數值 顯示 格式 format style 設置 eg: pi format longE; or 2.清除指令 clc 清除命令行窗口 clear 清除工作區 cls 3.搜索路徑設置 path(path,E:\ads\) or addpath 4.M文件 用戶把要實現的命令寫在一個以.m為擴展的文件中&#xff0c;然后由matlab系統進行解讀…

AnyDesk遠程工具免費版,v9.5.110綠色便攜版,秒連遠程桌面,剪貼板同步超實用

[軟件名稱]: AnyDesk遠程工具免費版 [軟件大小]: 7.5 MB [軟件大小]: 夸克網盤 | 百度網盤 軟件介紹 AnyDesk 讓遠程工作變得輕而易舉。無論您身處辦公室的另一端還是世界的另一側&#xff0c;只需在設備上下載、安裝并啟動 AnyDesk.exe&#xff0c;即可輕松訪問遠程屏幕。…

AI: 給Gemini CLI配上“說明書”, 精通的GEMINI.md項目記憶

嘿&#xff0c;各位技術同好&#xff01;今天我們來聊一個能極大提升AI編程助手效率的酷炫功能——Google Gemini CLI 中的 GEMINI.md 文件。 在日常開發中&#xff0c;我們越來越依賴像 Gemini 這樣的 AI 助手來幫我們寫代碼、調試 Bug 甚至重構項目。但大家是否遇到過這種情況…

[激光原理與應用-205]:光學器件 - LD與DFB的比較

一、相同點核心原理均基于半導體材料的受激輻射機制&#xff0c;通過電子-空穴復合產生光子。依賴諧振腔實現光反饋與放大&#xff0c;形成激光振蕩。采用電泵浦方式驅動&#xff0c;電流注入激發載流子&#xff0c;實現粒子數反轉。材料體系主要使用III-V族化合物半導體&#…

Cursor手機版:一半是神,一半是坑

大家好&#xff0c;我是羊仔&#xff0c;專注AI工具、智能體、編程。今天想和大家聊的這個工具&#xff0c;叫Cursor&#xff0c;可能很多朋友已經不陌生了&#xff0c;它作為一款AI原生代碼編輯器&#xff0c;之前可謂是風光無兩。但最近&#xff0c;它又搞了點新花樣&#xf…

康養休閑旅游服務虛擬仿真實訓室:筑牢技能人才培養的數字基石

隨著康養休閑旅游行業數字化、網絡化、智能化發展趨勢的深化&#xff0c;行業對高素質技能人才的實踐能力和數字素養提出了更高要求。康養休閑旅游服務虛擬仿真實訓室作為對接行業需求、創新實踐教學模式的重要載體&#xff0c;正成為中等職業教育康養休閑旅游服務專業人才培養…

【Python 高頻 API 速學 ⑤】

一、為什么把字典和集合放同一篇&#xff1f; ? 底層都是哈希表&#xff0c;API 設計高度對稱。 ? 日常任務無非「讀-寫-去重-集合運算」&#xff0c;這 5 個方法就能打穿。二、三件套 & 二板斧一覽名稱作用返回值原地&#xff1f;dict.get(key, default)安全讀取值或 de…

el-tree方法的整理

1.點擊樹的文字不要收縮僅點擊圖標的時候收縮 expand-on-click-node&#xff1a;是否在點擊節點的時候展開或者收縮節點&#xff0c; 默認值為 true&#xff0c;如果為 false&#xff0c;則只有點箭頭圖標的時候才會展開或者收縮節點。<el-tree:expand-on-click-node"f…

支持多網絡協議的測試工具(postman被無視版)

本文介紹接口調試工具&#xff0c;盡可能覆蓋支持多種網絡協議。寫給一直寫http接口&#xff0c;突然調試其他協議接口的開發 在后端開發中&#xff0c;接口調試工具的選擇取決于網絡協議類型和具體需求。以下是覆蓋多種協議的主流工具分類推薦&#xff0c;附關鍵特點和場景建議…

太陽平近點角詳解:概念、計算與應用

太陽平近點角詳解&#xff1a;概念、計算與應用 1. 基本定義 **太陽平近點角&#xff08;Mean Anomaly&#xff0c;M&#xff09;**是描述天體&#xff08;如地球&#xff09;在其軌道上平均運動位置的角度參數。對于太陽系中的行星或衛星而言&#xff0c;它表示假設天體以恒定…

ruoyi關閉shiro校驗,任何接口可以直接訪問

文章目錄1.找到ShiroConfig.java文件2.上述適用于get請求&#xff0c;post請求如何關閉&#xff1f;1.找到ShiroConfig.java文件 修改代碼 // 原始代碼 filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession,csrfValidateFilt…

數據結構進階 詳談紅黑樹

目錄 1. 紅?樹的概念 紅?樹的規則 紅?樹如何確保最?路徑不超過最短路徑的2倍的&#xff1f; 紅?樹的效率&#xff1a; 2. 紅?樹的實現 紅?樹的結構 紅?樹的插? 紅?樹樹插??個值的?概過程 情況1&#xff1a;變? 情況2&#xff1a;單旋變? 情況3&#…

【MySQL】MySQL去重查詢詳解

前言 在日常的數據庫操作中&#xff0c;數據去重是一個非常常見的需求。無論是查詢結果去重、數據清洗&#xff0c;還是統計分析&#xff0c;我們都需要掌握MySQL中的各種去重技術。本文將詳細介紹MySQL中常用的去重關鍵字和操作方法&#xff0c;結合實際業務場景&#xff0c;幫…

Pinterest視覺營銷自動化:亞矩陣云手機實例與多分辨率適配技術

Pinterest月活突破4.5億的視覺經濟時代&#xff0c;多分辨率適配與跨設備一致性成為品牌觸達用戶的核心挑戰。傳統營銷因素材模糊、設備參數固化&#xff08;如固定分辨率1080P&#xff09;、行為機械化&#xff08;如定時批量上傳&#xff09;&#xff0c;導致點擊率低于行業均…

01數據結構-圖的鄰接矩陣和遍歷

01數據結構-圖的鄰接矩陣和遍歷1.圖的遍歷1.1深度優先遍歷1.2廣度優先搜索2.鄰接矩陣的代碼實現1.圖的遍歷 1.1深度優先遍歷 深度優先搜索的過程類似于樹的先序遍歷&#xff0c;首先從例子中體會深度優先搜索&#xff0c;例如下圖1是個無向圖&#xff0c;采用深度優先算法遍歷…

OpenAI發布的GPT-5 更新了哪些內容,它的核心能力有哪些?AI編碼能力這么強,前端程序員何去何從?

目錄**1. GPT-5的核心能力與技術突破****1.1 智能水平的質變****1.2 代碼生成與優化****1.3 上下文處理與長文本能力****1.4 安全與可靠性改進****2. GPT-5的應用場景與案例****2.1 醫療領域****2.2 教育與學習****2.3 企業級應用****2.4 軟件開發****3. 技術細節與創新****3.1…

【無標題】AI 賦能日常效率:實用案例與操作心得分享

大語言模型&#xff08;LLM&#xff09;早已不再是實驗室里的專屬品&#xff0c;而是逐漸滲透到我們工作與生活的方方面面。從繁瑣的文檔處理到復雜的信息篩選&#xff0c;從學習輔助到日常規劃&#xff0c;AI 正以 "微生產力" 的形式重塑我們的效率邊界。本文將分享…

Java-線程線程的創建方式

一.進程和線程進程&#xff1a;進程是資源分配的基本單位&#xff0c;每個進程都有自己獨立的內存空間&#xff0c;可以看作是一個正在運行的程序實例線程&#xff1a;線程是CPU調度的基本單位&#xff0c;屬于進程&#xff0c;一個進程可以包含多個線程。線程共享進程的內存空…

Electron 中 license-keys 的完整集成方案

secure-electron-license-keys 是一個專門為 Electron 應用設計的 npm 包&#xff0c;用于實現離線許可證密鑰的創建、驗證和管理&#xff0c;幫助開發者保護應用程序&#xff0c;確保只有擁有合法許可證的用戶才能使用。以下是關于它的詳細介紹&#xff1a; 在 Electron 應用中…

AI推理的“靈魂五問”:直面2025算力鴻溝與中國的破局之路

摘要&#xff1a;2025年&#xff0c;AI產業的重心已從訓練全面轉向推理&#xff0c;但一場嚴峻的“體驗”危機正悄然上演。中美AI推理性能的巨大鴻溝&#xff0c;正讓國內廠商面臨用戶流失的切膚之痛。本文以問答形式&#xff0c;直面當前中國AI產業在推理“最后一公里”上最尖…