ZmjOS单片机裸机编程风格 > DV_Spaker(STC系列的PWM方式的pcm音频输出驱动)


这是基于STC系列的PWM方式输出pcm音频的驱动,PC通过uart将pcm数据发送下来之后再通过pwm方式将PCM数据输出,采样率为8k,调制频率为58593.75,代码如下:

		//以下是DV_Timer.H头文件部分
		/*******************************************************************************************
		文档说明:板载spaker驱动文件头文件
		*******************************************************************************************/
		//硬件资源占用:
		//GPIO tim0
		//设备模式描述:
		//接口函数:
		void DV_Spaker_Init(void);
		void DV_Spaker_Service(void);
		
		//以下是DV_Timer.c正文文件部分
		#include "stc15w.h"
		#include "Drive_Spaker.h"
		#define CCP_S1 0x10                 //P_SW1.4
		#define CCP_S0 0x20                 //P_SW1.5
		#define LED_Port		P25
		extern unsigned short uartidex;//cmd字符计数器、cmd有效与否检测
		extern unsigned short uartmax;
		unsigned short timeridex = 0;
		unsigned short timermax = 256;
		xdata unsigned char buf[64] = { 0 };//每次1个字符作为控制命令
		//注意系统时钟应该设置为33.000MHz
		/*******************************************************************************************
		函数说明:初始化io口并配置状态
		参数:
		输出:
		*******************************************************************************************/
		void DV_Spaker_Init()
		{
			ACC = P_SW1;
			ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=0 CCP_S1=0
			P_SW1 = ACC;                    //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)
	
		//	ACC = P_SW1;
		//	ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=1 CCP_S1=0
		//	ACC |= CCP_S0;                  //(P3.4/ECI_2, P3.5/CCP0_2, P3.6/CCP1_2, P3.7/CCP2_2)
		//	P_SW1 = ACC;
	
			//45.35147微秒@33.000MHz
			AUXR |= 0x80;		//定时器时钟1T模式
			TMOD &= 0xF0;		//设置定时器模式
			TL0 = 0x27;		//设置定时初值
			TH0 = 0xFA;		//设置定时初值
			TF0 = 0;		//清除TF0标志
			TR0 = 1;		//定时器0开始计时
			ET0 = 1;
	
			CCON = 0;                       //初始化PCA控制寄存器
																			//PCA定时器停止
																			//清除CF标志
																			//清除模块中断标志
			CL = 0;                         //复位PCA寄存器
			CH = 0;
	
			CMOD = 0x04;                    //设置PCA时钟源2分频//最终被调制频率为58,593.75
																			//允许PCA定时器溢出中断
			PCA_PWM0 = 0x0A;                //PCA模块0工作于8位PWM
			CCAP0H = CCAP0L = 0x06;         //PWM0的占空比为25% ((40H-30H)/40H)
			CCAPM0 = 0x24;                  //PCA模块0为8位PWM模式
	
		//	PCA_PWM1 = 0x06;                //PCA模块1工作于8位PWM
		//	CCAP1H = CCAP1L = 0x06;         //PWM1的占空比为25% ((40H-30H)/40H)
		//	CCAPM1 = 0x24;                  //PCA模块1为8位PWM模式
	
			CR = 1;                         //PCA定时器开始工作
			EA = 1;
	
			LED_Port = 0;
		}
		/*******************************************************************************************
		函数说明:
		参数:
		输出:
		*******************************************************************************************/
		void Timer0() interrupt 1 using 1
		{
			if(timeridex < timermax)
				CCAP0H = CCAP0L = buf[timeridex++];
				//SBUF = buf[timeridex++];
			else
				CCAP0H = CCAP0L = 0;
		}
		/*******************************************************************************************
		函数说明:
		参数:
		输出:
		*******************************************************************************************/
		void DV_Spaker_Service()
		{
			if((timeridex >= timermax) && (uartidex >= uartmax))
			{
				//交换缓冲区
				if(timermax == 128){
					timeridex = 128;
					timermax = 0;
					uartidex = 0;
					uartmax = 128;
				}
				else{
					timeridex = 0;
					timermax = 128;
					uartidex = 128;
					uartmax = 0;
				}
				SBUF = 0X30;//通知上位机数据准备好了
			}
		}