天天看點

STM32的PWM和DAC的練習

摘要:

本文用PWM輸出波形控制IO口實作呼吸燈,并通過DAC輸出2KHz的正弦波和編輯音頻輸出的功能。

文章目錄

      • 摘要:
      • 一. PWM練習
        • 1. PWM簡介
        • 2. PWM輸出配置
        • 3. 主要代碼
        • 4.示範效果
          • a. 模拟示波器顯示
          • b. 示波器顯示
          • c. 實物效果
      • 二. DAC練習
        • 1. DAC簡介
        • 2.要點分析并實作2KHz正弦波的輸出
        • 4. 設計輸出音頻信号
      • 三. 總結

一. PWM練習

1. PWM簡介

PWM是 Pulse Width Modulation 的縮寫,中文意思就是脈沖寬度調制,簡稱脈寬調制。它是利用微處理器的數字輸出來對模拟電路進行控 制的一種非常有效的技術,其控制簡單、靈活和動态響應好等優點而成 為電力電子技術最廣泛應用的控制方式。

其原理圖如下:

STM32的PWM和DAC的練習

STM32F1除了基本定時器TIM6和TIM7,其他定時器都可以産生PWM輸出 。其中進階定時器 TIM1 和 TIM8 可以同時産生多達 7 路的 PWM 輸出 。而通用定時器也能同時産生多達 4路的 PWM 輸出,這些在定時器中斷 章節中已經介紹過。 PWM的輸出其實就是對外輸出脈寬可調(即占空比調節)的方波信号 ,信号頻率是由自動重裝寄存器 ARR 的值決定,占空比由比較寄存器 CCR 的值決定。PWM輸出比較模式總共有8種,具體由寄存器 CCMRx 的位 OCxM[2:0] 配置。我們這裡隻講解最常用的兩種PWM輸出模式:PWM1和PWM2,其他幾 種模式可以參考《STM32F10x中文參考手冊》13、14、15定時器章節。

更多知識可以參考stm32 PWM輸出實驗

2. PWM輸出配置

1)配置使能端口時鐘,設定引腳複用器映射

STM32的PWM和DAC的練習

2)初始化定時器參數,包含自動重裝值,分頻系數,計數方式等

初始化PWM輸出參數,包含輸出極性,使能等

STM32的PWM和DAC的練習

3)開定時器

STM32的PWM和DAC的練習

4)之後在主函數中控制占空比:

這時while(1)裡循環得代碼,作用就是led0pwmval占空比逐漸增大,也就是越來越亮。在
delay_ms(10);	 
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;										 
TIM_SetCompare2(TIM3,led0pwmval);	
           

3. 主要代碼

void TIM3_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時鐘使能

	TIM_TimeBaseStructure.TIM_Period = arr; //設定在下一個更新事件裝入活動的自動重裝載寄存器周期的值	 計數到5000為500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //設定用來作為TIMx時鐘頻率除數的預分頻值  10Khz的計數頻率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設定時鐘分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計數模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數機關
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷

	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中斷
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占優先級0級
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //從優先級3級
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外設
							 
}
//定時器3中斷服務程式
void TIM3_IRQHandler(void)   //TIM3中斷
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查指定的TIM中斷發生與否:TIM 中斷源 
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中斷待處理位:TIM 中斷源 
		LED1=!LED1;
		}
}
//TIM3 PWM部分初始化 
//PWM輸出初始化
//arr:自動重裝值
//psc:時鐘預分頻數
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定時器3時鐘
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外設和AFIO複用功能子產品時鐘
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    
 
   //設定該引腳為複用輸出功能,輸出TIM3 CH2的PWM脈沖波形	GPIOB.5
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //複用推挽輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
 
   //初始化TIM3
	TIM_TimeBaseStructure.TIM_Period = arr; //設定在下一個更新事件裝入活動的自動重裝載寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //設定用來作為TIMx時鐘頻率除數的預分頻值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設定時鐘分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計數模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數機關
	
	//初始化TIM3 Channel2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時器模式:TIM脈沖寬度調制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根據T指定的參數初始化外設TIM3 OC2

	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的預裝載寄存器
 
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
	

}
           

4.示範效果

a. 模拟示波器顯示

選擇魔術棒–Debug–配置如下

STM32的PWM和DAC的練習

示波器配置如下:

STM32的PWM和DAC的練習
STM32的PWM和DAC的練習

顯示效果:

STM32的PWM和DAC的練習
b. 示波器顯示
STM32的PWM和DAC的練習
c. 實物效果
STM32的PWM和DAC的練習

二. DAC練習

1. DAC簡介

  • DAC為數字/模拟轉換子產品,故名思議,它的作用就是把輸入的數字編碼,轉換成對應的模拟電壓輸出,它的功能與ADC相反。在常見的數字信号系統中,大部分傳感器信号被化成電壓信号,而ADC把電壓模拟信号轉換成易于計算機存儲、處理的數字編碼,由計算機處理完成後,再由DAC輸出電壓模拟信号,該電壓模拟信号常常用來驅動某些執行器件,使人類易于感覺。如音頻信号的采集及還原就是這樣一個過程。
  • STM32具有片上DAC外設,它的分辯率可配置為8位或12位的數字輸入信号,具有兩個DAC輸出通道,這兩個通道互不影響,每個通道都可以使用DMA功能,都具有出錯檢測能力,可外部觸發。
  • DAC子產品圖如下:
STM32的PWM和DAC的練習

整個DAC子產品圍繞框圖下方的**“數字至模拟轉換器x”**展開,它的左邊分别是參考電源的引腳:VDDA、VSSA及Vref+,其中STM32的DAC規定了它的參考電壓Vref+輸入範圍為2.4–3.3V。“數字至模拟轉換器x”的輸入為DAC的資料寄存器“DORx”的數字編碼,經過它轉換得的模拟信号由圖中右側的“ DAC OUTX”輸出。而資料寄存器“DORx“又受“控制邏輯”支配,它可以控制資料寄存器加入一些僞噪聲信号或配置産生三角波信号。圖中的左上角為DAC的觸發源,DAC根據觸發源的信号來進行DAC轉換,其作用就相當于DAC轉換器的開關,它可以配置的觸發源為外部中斷源觸發、定時器觸發或軟體控制觸發。如本章實驗中需要控制正弦波的頻率,就需要定時器定時觸發DAC進行資料轉換。

2.要點分析并實作2KHz正弦波的輸出

STM32的PWM和DAC的練習
  • DAC_Trigger 用于配置DAC的觸發方式
  • DAC_WaveGeneration為是否啟動輸出噪聲或者三角波
  • DAC_LFSRUnmask_TriangleAmpliude 為選擇噪聲生成器的低通濾波或三角波的幅值
  • DAC_OutputBuffer 選擇是否使能輸出緩存器

    更多步驟請參考

    《【野火®】零死角玩轉STM32—F103-MINI》

    根據公式:
    STM32的PWM和DAC的練習

設定如下

STM32的PWM和DAC的練習

這樣即可輸出2Khz的正弦波

結果如下:

STM32的PWM和DAC的練習

接入蜂鳴器,聽有單音。

STM32的PWM和DAC的練習

4. 設計輸出音頻信号

算法邏輯類似與輸出正弦波信号的思路一緻,不同的是要更改采樣的數值。

step1:打開

Adobe Audition

打開自己喜歡的音樂,設定:

  • 采樣率8000
  • 單聲道
  • 16位
  • 大約采集2-3s
STM32的PWM和DAC的練習

step2:存儲為.wav檔案

.wav檔案通過軟體

Uedit32

打開

STM32的PWM和DAC的練習

step3:格式轉換

全選内容,右鍵–用16進制複制所選視圖,複制到記事本–粘貼回去–右鍵–選擇範圍

STM32的PWM和DAC的練習

step4:複制到notepad++進行填充

關于

notepad++

前文提到過用法,

按列塊插入

0x

,

每列重複操作

STM32的PWM和DAC的練習
STM32的PWM和DAC的練習

step5:修改數組

STM32的PWM和DAC的練習

step6:燒入觀察波形

STM32的PWM和DAC的練習
STM32的PWM和DAC的練習

三. 總結

這次實驗,嘗試了解了DAC和PWM,這兩個子產品在時機中應用十分廣泛,比如在一些比賽中可以用PWM波控制舵機和點選,用ADC,DAC進行采集資訊等。收獲許多

參考

[1] 使用STM32控制無源蜂鳴器發聲播放音樂(STM32_07)

[2] stm32 PMW輸出實驗

[3] 詳解基于STM32的keil4 MDK 軟體仿真輸出IO口的波形圖!