實現功能:采用定時器2的通道2,使PA1輸出頻率1K,占空比40的PWM波形,用PA8隨意延時取反led燈,指示程序運行。
首先熟悉一下定時器的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通用定時器---基本定時學習
下一篇:STM32F10x 學習筆記之解決JLink 無法下載程序的問題
推薦閱讀
史海拾趣
ACCRETECH是一家日本的半導體設備制造公司,以下是該公司發展的五個相關故事:
公司成立和早期發展: ACCRETECH(前身為TOKYO SEIMITSU)成立于1949年,總部位于日本東京。最初,公司主要從事機械零件的生產,隨著時代的發展,逐漸轉型為半導體設備制造商。起初,ACCRETECH主要生產晶圓表面檢測設備和測量設備。
技術創新和產品拓展: 隨著半導體行業的快速發展,ACCRETECH不斷進行技術創新,并逐步拓展產品線。公司推出了包括晶圓尺寸測量儀、晶圓表面檢測儀、晶圓平整度檢測儀等在內的多種半導體生產設備,滿足了客戶對高精度、高效率設備的需求。
市場擴張和國際合作: ACCRETECH積極拓展國內外市場,并與全球各地的客戶建立了合作關系。公司的產品被廣泛應用于半導體制造、集成電路測試、電子元件生產等領域,贏得了客戶的信賴。ACCRETECH還與國際知名半導體企業展開合作,共同推動技術進步和產業發展。
持續投入研發和創新: ACCRETECH不斷加大研發投入,致力于技術創新和產品升級。公司設立了專門的研究機構和實驗室,擁有一支技術精湛的團隊,致力于開發新產品和解決方案,滿足客戶不斷提高的需求。
未來發展展望: ACCRETECH將繼續致力于半導體設備制造領域的研發和應用,不斷推出更先進、更可靠的產品和解決方案,滿足客戶在半導體生產過程中的需求。公司將加強國際市場拓展,提升自身在全球市場的競爭力,為行業的發展做出更大的貢獻。
奇力公司的成功離不開與奇美集團的緊密合作。奇美集團是臺灣知名的面板生產廠家,擁有強大的技術實力和市場份額。奇力公司作為奇美集團的子公司,得到了奇美集團在技術、資金和市場等方面的全力支持。通過與奇美集團的緊密合作,奇力公司得以快速發展,并在LED芯片市場上取得了顯著的成績。
DIALIGHT公司一直專注于工業LED照明領域的發展。他們深入了解工業空間照明的需求和挑戰,設計了一系列專為工業應用而定制的LED照明產品。這些產品不僅易于安裝和維護,而且能在惡劣的環境下持續使用。此外,DIALIGHT還提供集成系統解決方案,幫助客戶降低能源成本、維護成本和碳足跡,同時提高設施的安全性和生產力。通過不斷創新和優質服務,DIALIGHT在工業LED照明領域贏得了廣泛的認可和信賴。
蘇州鋒馳深知知識產權的重要性,公司高度重視技術創新和知識產權保護工作。截至目前,蘇州鋒馳已擁有商標信息2條、專利信息13條,這些知識產權的積累為公司的持續發展提供了有力的保障。同時,公司還積極參與行業標準制定和技術交流活動,不斷提升自身的技術水平和行業影響力。
在技術和產品的雙重驅動下,Dresden Elektronik公司開始積極拓展市場。他們不僅在國內市場上取得了顯著的成績,還積極開拓國際市場。通過參加國際展會、與跨國企業合作等方式,公司的知名度和影響力逐漸提升,市場份額也不斷擴大。
到了1960年,Chauvin Arnoux推出了Monoc測試儀,這是一種帶有旋轉開關和統一測量刻度的測量儀器。Monoc測試儀以其簡潔、直觀的操作界面和精確的測量能力,迅速成為電工行業的首選測量工具。這一產品的普及,進一步鞏固了Chauvin Arnoux在電氣測量領域的領導地位。
功率變換技術是按用戶需求改變電能應用方式(改變電能的波形、頻率等)的技術;可以有AC/DC、DC/DC、DC/AC、AC/AC及其相互組合的多種變換。40年代前后,由電磁元件組合形成的各種功率變換過程基本上可實現清潔電源。例如,將交流電動機與直流發 ...… 查看全部問答∨ |
|
工信部首次明確3G牌照歸屬 年底或明年初發照 http://tech.163.com/08/1212/11/4SV7EQOV000915BE.html 工業和信息化部部長李毅中今日稱,根據綜合考慮,我們將通過一定的程序在年底或明年年初發放3G牌照 ...… 查看全部問答∨ |
誰知道有增益帶寬積達到100M以上的放大器?急........... 誰知道有增益帶寬積達到100M以上的放大器,并且可以放大直流信號? 謝謝大家了......................… 查看全部問答∨ |
作為第四代的照明燈具,LED 照明燈具一經推出就成為照明市場的寵兒,節能降碳、長壽命成為其經典的賣點。LED 高節能:節省能源無污染即為環保,直流驅動,超低功耗(單管0.03 瓦-1 瓦)電光功率轉換接近 90%,相同照明效果比傳 ...… 查看全部問答∨ |
|
我講外部RAM存儲數據,內部RAM放堆棧,程序很簡單,就是將外部ram復制,同時讀取,讀取后用串口發出來,我用JLINK調試,程序始終停在串口等待處,查看賦值也不對。我手動復位板子,不用JLINK帶,STM32能夠對外部RAM賦值,并且能夠從串口輸出來 ...… 查看全部問答∨ |