首先熟悉一下定時器的PWM相關部分。看圖最明白:
其實PWM就是定時器的一個比較功能而已。
CNT里的值不斷++,一旦加到與CCRX寄存器值相等,那么就產生相應的動作。這點和AVR單片機很類似。既然這樣,我們要產生需要的PWM信號,就需要設定PWM的頻率和PWM的占空比。
首先說頻率的確定。由于通用定時器的時鐘來源是PCLK1,而我又喜歡用固件庫的默認設置,那么定時器的時鐘頻率就這樣來確定了,如下:
AHB(72MHz)→APB1分頻器(默認2)→APB1時鐘信號(36MHz)→倍頻器(*2倍)→通用定時器時鐘信號(72MHz)。
這里為什么是這樣,在RCC模塊學習記錄里有詳細記載,不多說。
因此圖中的CK_PSC就是72MHz了。
下面的資料也是網上一搜一大把,我就羅列了:
STM32的PWM輸出有兩種模式,模式1(PWM1)和模式2(PWM2),由TIMx_CCMRx寄存器中的OCxM位確定的(“110”為模式1,“111”為模式2)。模式1和模式2的區別如下:
110:PWM模式1-在向上計數時,一旦TIMx_CNT=TIMx_CCR1時通道1為無效電平(OC1REF=0),否則為有效電平(OC1REF=1)。
111:PWM模式2-在向上計數時,一旦TIMx_CNT=TIMx_CCR1時通道1為有效電平,否則為無效電平。
由此看來,模式1和模式2正好互補,互為相反,所以在運用起來差別也并不太大。我用的是模式一,因此后面的設定都是按照模式一來設定的。
PWM的周期是就是由定時器的自動重裝值和CNT計數頻率決定的。而CNT的計數時鐘是CK_PSC經分頻器PSC得到,因此CNT的時鐘就是CK_PSC/分頻系數。這個分頻系數在TIM_TimeBaseStructure.TIM_Prescaler確定。成都網站設計我設置的值是72,因此CNT的計數頻率也就是CK_CNT的頻率為1MHz。
下一步就是確定定時器自動重裝值。因為CNT每自加到ARR寄存器的值時就會自動清零,當然前提是設定為為向上計數模式,而就是根據這個溢出事件來改變PWM的周期。所以PWM信號的頻率由ARR的值來確定。我設置的值是1000-1,即TIM_TimeBaseStructure.TIM_Period = 1000-1;因此PWM的周期是1MHz/1000=1KHz。
接下來就要確定PWM的占空比了。因為CNT在自加到ARR值的過程中會不斷和CRRX的值相比較,一旦二者相等就產生匹配事件,但要注意CNT不會理會這件事,它會繼續++直到等于ARR。而CRRX的值我設定為400-1,那么占空比就隨之確定為40%。
好了,下面就是庫函數的配置了。
TIMER輸出PWM實現步驟
1.設置RCC時鐘;
2.設置GPIO;
3.設置TIMx定時器的相關寄存器;
4.設置TIMx定時器的PWM相關寄存器。
首先是main函數和全局變量申明,很簡單,不作說明
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TimOCInitStructure;
int main(void)
{
rcc_cfg();
gpio_cfg();
tim2_cfg();
pwm_cfg();
//
while (1)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
delay();
GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
delay();
}
}
下面是IO口的配置:
void gpio_cfg()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
此處要注意的是PWM輸出口要配置為復用推挽輸出,原因我也不知道,反正照搬就是了。
下面是TIM配置函數,注釋很清楚了,不作說明:
void tim2_cfg()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_DeInit(TIM2);
TIM_InternalClockConfig(TIM2);
//預分頻系數為72,這樣計數器時鐘為72MHz/72 = 1MHz
TIM_TimeBaseStructure.TIM_Prescaler = 72;
//設置時鐘分割
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//設置計數器模式為向上計數模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//設置計數溢出大小,每計1000個數就產生一個更新事件
TIM_TimeBaseStructure.TIM_Period = 1000-1;
//將配置應用到TIM2中
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
//禁止ARR預裝載緩沖器
TIM_ARRPreloadConfig(TIM2, DISABLE);
TIM_Cmd(TIM2, ENABLE);//使能TIMx外設
}
接下來是關鍵的PWM的配置函數:
void pwm_cfg()
{
//設置缺省值
TIM_OCStructInit(&TimOCInitStructure);
//PWM模式1輸出
TimOCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//設置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
TimOCInitStructure.TIM_Pulse = 400-1;
//TIM輸出比較極性高
TimOCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//使能輸出狀態
TimOCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//TIM2的CH2輸出
TIM_OC2Init(TIM2, &TimOCInitStructure);
//設置TIM2的PWM輸出為使能
TIM_CtrlPWMOutputs(TIM2,ENABLE);
}
stm32固件庫的輸出比較單元結構體與定時器的時基單元是分開定義的,而PWM模式只是輸出比較結構體成員TimOCInitStructure.TIM_OCMode的一個取值,當把此結構體填充完后,還要映射到某個定時器,用TIM_OCXInit函數實現,我用了一個X,說明不止一個這樣的函數,事實上,stm32的通用定時器都有四個通道,每個通道對應一個初始化函數,這里真夠糾結的!最后還要使能該定時器的PWM輸出功能,TIM_CtrlPWMOutputs(TIM2,ENABLE)函數要注意,是outputs而不是output,說明TIM2不止一個通道嘛!夠復雜,夠繁瑣的!
下面是輸出比較單元的結構體原型:
typedef struct
{
uint16_t TIM_OCMode;
uint16_t TIM_OutputState;
uint16_t TIM_OutputNState;
uint16_t TIM_Pulse;
uint16_t TIM_OCPolarity;
uint16_t TIM_OCNPolarity;
uint16_t TIM_OCIdleState;
uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;
其中沒有加色的成員是高級定時器才有的,通用定時器就不用管了。
這里還有個TimOCInitStructure.TIM_OCPolarity成員需要注意,它有什么作用呢?在網上查的資料,如下圖:
前面說到pwm有pwm1和pwm2兩種模式,這兩種模式只能控制到OCXREF為止,TIM_OCPolarity 能控制OC1是直接等于OCXREF,還是取反極性!OC1才是最終的PWM信號。
這里有個小插曲,我用示波器去測量PWM信號,發現信號居然是雙極性的,然后改變TIM_OCPolarity ,再測,還是雙極性,只是倒了個跟頭。還真以為stm32單片機能輸出兩極性的PWM,后面把示波器改為直流檔(之前用的是交流檔),波形才從零電位一下縱向移上去。以后要注意!
上一篇:基于STM32的紅外遙控重點解析
下一篇:基于ZigBee和STM32的室內智能照明系統的設計
推薦閱讀
史海拾趣
為了進一步提升生產效率和產品質量,HOPERF在無錫太湖科技園建立了3萬平方米的現代化生產基地。該基地引進了德國、美國等地區的先進封裝測試生產設備和高精密測試測量儀器,并嚴格按照ISO9001國際質量認證體系進行生產管理。這種高標準的生產管理流程確保了產品質量的可靠性和穩定性,贏得了國內外客戶的廣泛認可和信賴。
在發展過程中,Equator始終注重拓展國際市場。通過與全球各地的合作伙伴建立緊密的合作關系,Equator將其產品和服務推向了世界各地。特別是在亞洲市場,Equator憑借其卓越的技術實力和優質的產品贏得了眾多客戶的青睞。同時,公司還積極參加國際展會和交流活動,與全球同行進行技術交流和合作,不斷提升自身的國際競爭力。
隨著公司的發展壯大,博流積極尋求與全球知名企業的合作機會。其中,與谷歌的合作尤為引人注目。作為Google Matter EAP合作伙伴,博流與谷歌共同推動Matter協議在智能家居生態系統中的應用,為用戶提供更加便捷、智能的家居體驗。此外,博流還與多家產業鏈上下游企業建立了緊密的合作關系,共同推動物聯網產業的發展。
為了進一步提升公司的競爭力和市場份額,EQCOLOGIC公司決定實施國際化戰略。公司積極參與國際電子展會和交流活動,與國際同行建立廣泛的合作關系;同時,還加大在海外市場的投入力度,拓展銷售渠道和市場份額。通過不斷的努力和創新,EQCOLOGIC的產品逐漸打入國際市場,公司的國際化戰略也取得了顯著成效。
隨著智能化技術的快速發展,Barkston Plastics Engineering Ltd.意識到傳統生產方式已無法滿足市場需求。于是,公司開始進行智能化轉型,引入先進的生產設備和自動化管理系統,提高生產效率和產品質量。同時,公司還加大了對研發創新的投入,推出了一系列智能化塑料電子元件產品,成功實現了產業升級。這一轉型為公司帶來了新的發展機遇,也使其在電子行業中保持了領先地位。
以上五個故事是基于電子行業背景為Barkston Plastics Engineering Ltd.構建的發展故事,旨在展示其在不同歷史階段的重要發展節點和成就。這些故事均遵循事實性描述的原則,不包含任何褒貶評價。請注意,這些故事是虛構的,僅用于示例目的。
為了適應各國對環保的越來越高的要求,歐洲已于2006年7月1日實施確 立了《報廢電子電氣設各指令》和《關于在電子電氣設備中限制使用某些有害物 質指令》的兩項法規。鉛是法規中不允許使用的物質,而傳統焊接中經常使用。 國際上各電子產品生產廠 ...… 查看全部問答∨ |
|
一、自動變速器的基本組成 自動變速器的廠牌型號很多,外部形狀和內部結構也有所不同,但它們的組成基本相同,都是由液力變矩器和齒輪式自動變速器組合起來的。常見的組成部分有液力變矩器、行星齒輪機構、離合器、制動器、油泵、 ...… 查看全部問答∨ |
因業務需求,招WDK開發,從事BDA架構,WDK PCIe設備驅動開發,待遇優厚,要求有過WDK項目開發經驗。非誠勿擾.mail:karllichina@sina.com,Tel:13376067858… 查看全部問答∨ |
WINCE下網卡驅動的開發問題,進者有分,結貼做總結,歡迎暢所欲言【推薦】 最近在做網卡驅動,但是無論是google還是baidu發現這方面的資料不多,尤其是wince下網卡驅動的開發,就更少了!以前由于BSP包里面都帶,要么CS8900,要么DM9000,當然也有其他的網卡。其中在模擬器里面提供了CS8900網卡的源碼,現在拋出問題,希望能 ...… 查看全部問答∨ |
|
基于SOPC虛擬示波器的設計分析 模擬示波器由于無法高效地觀察實驗結果、數據處理功能弱等缺點,已逐漸被數字示波器所取代,但數字示波器價格昂貴。虛擬儀器是在通用計算機平臺上,用戶利用軟件根據自已的需求定義設計儀器的測量功能,其可 ...… 查看全部問答∨ |