單片機輸出模擬量,主要有兩種方式,通過DA模塊或者PWM模塊輸出;

以我目前經常使用的ST的Cortex-M0系列的處理STM32F051處理器為例。

在我負責的產品中,有一款產品需要由單片機產生鈴聲,為了節省成本,沒有使用專用的鈴聲芯片,而是由單片機的D/A模塊輸出模擬量以產生鈴聲,同時根據外接的可調電組,調節輸出的電壓幅度以調節的音量。

具體實現原理如下:

1)將產品部提供的wmv的鈴聲文件,通過goldenwave軟件按照16kHz的采樣率重新采樣。

2)將重采樣得到的音頻數據進行放縮平移轉成偏置為128,范圍為0-255之間的8bit整型的數據。

3)將得到的數據存儲到外置的SPI Flash。

4)選用單片機的某個定時器,將定時器的定時時間設置為62.5us,并使用中斷。

5)配置單片機的DA以及SPI模塊,在定時器中斷時,通過SPI模塊讀取其FIFO的數值,將讀到的數值通過DA模塊輸出到端口,同時發送命令通過SPI模塊讀取下一個byte的數據。

定時器中斷代碼如下:

if(SPI1->SR & SPI_SR_RXNE)

{

temp = SPI_Receive(SPI1);

DAC->DHR12R1 = (((U16)temp) << 2);

DAC->DHR12R1 = (((U16)temp) << 4);

}

if(SPI1->SR & SPI_SR_TXE)

{

SPI_SendData(SPI1, 0xFF);

addr ++;

}

另外一種常用的模擬量輸出的方式為PWM輸出。

即通過頻率固定,占空比可調的信號輸出PWM,PWM帶通過低通濾波電路濾成幅度受占空比控制的模擬量信號;

可以通過單片機的PWM模塊或者是直接用定時器中斷產生PWM信號。

PWM信號通過簡單的R、C低通濾波電路就可以濾成模擬量;

一般R、C的時間常數需要選為10倍的PWM信號的周期。

模擬量輸出的幅度為PWM信號的輸出高電平*占空比;

比如以下的程序,就是通過單片機的PWM模塊輸出10KHz的占空比,并通過時間常數為1ms(電阻為10k,電容為0.1uF)的R、C過濾成模擬量;

用來接入直流電機控制器,調節直接電機的轉速。

void fnMT_InitPWM(void){

SET_IO_AFMODE_PP(P_MOTOR_B_PULSE_PORT, P_MOTOR_B_PULSE_PIN); 

fnMN_MAPR_And(~AFIO_MAPR_TIM1_REMAP)

RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;//Timer1 clock enable

MOTOR_PWM->CR1 = TIM_CR1_ARPE;//自動加載

MOTOR_PWM->PSC = (64 - 1);//fck_psc/(PSC[15:0] + 1)=1MHz

MOTOR_PWM->EGR = 0x0001;//Reload immediate

MOTOR_PWM->CCMR1 = 0x0068;//使能PWM功能,并開啟自動加載CH1 

MOTOR_PWM->ARR = (U16)(MOTOR_FREQ_DEFAULT - 1); 

MOTOR_PWM->CCR1 = 100; 

MOTOR_PWM->BDTR = 0x8000; 

MOTOR_PWM->EGR = 0x0001;

MOTOR_PWM->CCER |= 0x0009;

MOTOR_PWM->DIER |= 0x000001; 

MOTOR_PWM->CR1 |= 0x0001;

}

void fnMT_ConPWM(U16 period, U16 duty){ 

MOTOR_PWM->ARR = period; 

MOTOR_PWM->CCR1 = duty;

}