DSP28335课设:音乐流水灯的设计

本题目为音乐流水灯的设计,目的是熟练掌握DSP定时器的控制、中断系统的应用以及程序的编写调试。

1、让DSP发出不同的音乐音调;   

2、存储一个简单音乐(自选);

3、音乐的音调对应不同的灯

4、启动开关按下时,音乐流水灯开始运行,在播放音乐的同时,LED灯根据不同音调点亮;

5、按要求编写课程设计报告书,正确、完整的阐述设计和实验结果。

我们单片机的发声是通过蜂鸣器发出的,所以我们先了解一下蜂鸣器:

1.蜂鸣器介绍

             蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、 打印机、 复印机、 报警器、 电子玩具、 汽车电子设备、 电话机、 定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。  

             压电式蜂鸣器主要由多谐振荡器、 压电蜂鸣片、 阻抗匹配器及共鸣箱、 外壳等组成。 多谐振荡器由晶体管或集成电路构成, 当接通电源后( 1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号, 阻抗匹配器推动压电蜂鸣片发声。(无源蜂鸣器

所以要使蜂鸣器发声,只需要频率在1.5到5khz之间即可

下面我们通过一个实验使DSP芯片发声:

打开ccs软件

1.新建一个项目:在我之前的博客写过

2.项目中的文件如下:(采用的是模块化编程),每个模块写好之后具有移植性

leds.c

#include "leds.h"

/*******************************************************************************
* 函 数 名         : LED_Init
* 函数功能         : LED初始化函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void LED_Init(void)
{
    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟

    //LED1端口配置
    GpioCtrlRegs.GPCMUX1.bit.GPIO68=0;//设置为通用GPIO功能
    GpioCtrlRegs.GPCDIR.bit.GPIO68=1;//设置GPIO方向为输出
    GpioCtrlRegs.GPCPUD.bit.GPIO68=0;//使能GPIO上拉电阻

    //LED2端口配置
    GpioCtrlRegs.GPCMUX1.bit.GPIO67=0;
    GpioCtrlRegs.GPCDIR.bit.GPIO67=1;
    GpioCtrlRegs.GPCPUD.bit.GPIO67=0;

    //LED3端口配置
    GpioCtrlRegs.GPCMUX1.bit.GPIO66=0;
    GpioCtrlRegs.GPCDIR.bit.GPIO66=1;
    GpioCtrlRegs.GPCPUD.bit.GPIO66=0;

    //LED4端口配置
    GpioCtrlRegs.GPCMUX1.bit.GPIO65=0;
    GpioCtrlRegs.GPCDIR.bit.GPIO65=1;
    GpioCtrlRegs.GPCPUD.bit.GPIO65=0;

    //LED5端口配置
    GpioCtrlRegs.GPCMUX1.bit.GPIO64=0;
    GpioCtrlRegs.GPCDIR.bit.GPIO64=1;
    GpioCtrlRegs.GPCPUD.bit.GPIO64=0;

    //LED6端口配置
    GpioCtrlRegs.GPAMUX1.bit.GPIO10=0;
    GpioCtrlRegs.GPADIR.bit.GPIO10=1;
    GpioCtrlRegs.GPAPUD.bit.GPIO10=0;

    //LED7端口配置
    GpioCtrlRegs.GPAMUX1.bit.GPIO11=0;
    GpioCtrlRegs.GPADIR.bit.GPIO11=1;
    GpioCtrlRegs.GPAPUD.bit.GPIO11=0;



    GpioDataRegs.GPCSET.bit.GPIO68=1;
    GpioDataRegs.GPCSET.bit.GPIO67=1;
    GpioDataRegs.GPCSET.bit.GPIO66=1;
    GpioDataRegs.GPCSET.bit.GPIO65=1;
    GpioDataRegs.GPCSET.bit.GPIO64=1;
    GpioDataRegs.GPASET.bit.GPIO10=1;
    GpioDataRegs.GPASET.bit.GPIO11=1;

    EDIS;
}

leds.h

#ifndef _LEDS_H_
#define _LEDS_H_

#include "DSP2833x_Device.h"     // DSP2833x 头文件
#include "DSP2833x_Examples.h"   // DSP2833x 例子相关头文件


#define LED1_OFF        (GpioDataRegs.GPCSET.bit.GPIO68=1)
#define LED1_ON         (GpioDataRegs.GPCCLEAR.bit.GPIO68=1)
#define LED1_TOGGLE     (GpioDataRegs.GPCTOGGLE.bit.GPIO68=1)

#define LED2_OFF        (GpioDataRegs.GPCSET.bit.GPIO67=1)
#define LED2_ON         (GpioDataRegs.GPCCLEAR.bit.GPIO67=1)
#define LED2_TOGGLE     (GpioDataRegs.GPCTOGGLE.bit.GPIO67=1)

#define LED3_OFF        (GpioDataRegs.GPCSET.bit.GPIO66=1)
#define LED3_ON         (GpioDataRegs.GPCCLEAR.bit.GPIO66=1)
#define LED3_TOGGLE     (GpioDataRegs.GPCTOGGLE.bit.GPIO66=1)

#define LED4_OFF        (GpioDataRegs.GPCSET.bit.GPIO65=1)
#define LED4_ON         (GpioDataRegs.GPCCLEAR.bit.GPIO65=1)
#define LED4_TOGGLE     (GpioDataRegs.GPCTOGGLE.bit.GPIO65=1)

#define LED5_OFF        (GpioDataRegs.GPCSET.bit.GPIO64=1)
#define LED5_ON         (GpioDataRegs.GPCCLEAR.bit.GPIO64=1)
#define LED5_TOGGLE     (GpioDataRegs.GPCTOGGLE.bit.GPIO64=1)

#define LED6_OFF        (GpioDataRegs.GPASET.bit.GPIO10=1)
#define LED6_ON         (GpioDataRegs.GPACLEAR.bit.GPIO10=1)
#define LED6_TOGGLE     (GpioDataRegs.GPATOGGLE.bit.GPIO10=1)

#define LED7_OFF        (GpioDataRegs.GPASET.bit.GPIO11=1)
#define LED7_ON         (GpioDataRegs.GPACLEAR.bit.GPIO11=1)
#define LED7_TOGGLE     (GpioDataRegs.GPATOGGLE.bit.GPIO11=1)


void LED_Init(void);


#endif /* LED_H_ */

 beep.c

#include "beep.h"

void BEEP_Init(void)
{
    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK=1;//开启GPIO时钟
    //BEEP端口配置
    GpioCtrlRegs.GPAMUX1.bit.GPIO6=0;
    GpioCtrlRegs.GPADIR.bit.GPIO6=1;
    GpioCtrlRegs.GPAPUD.bit.GPIO6=0;

    EDIS;
    GpioDataRegs.GPACLEAR.bit.GPIO6=1;
}

beep.h

#ifndef BEEP_H_
#define BEEP_H_


#include "DSP2833x_Device.h"     // DSP2833x 头文件
#include "DSP2833x_Examples.h"   // DSP2833x 例子相关头文件


#define BEEP_ON         (GpioDataRegs.GPASET.bit.GPIO6=1)
#define BEEP_OFF        (GpioDataRegs.GPACLEAR.bit.GPIO6=1)
#define BEEP_TOGGLE     (GpioDataRegs.GPATOGGLE.bit.GPIO6=1)

void BEEP_Init(void);

#endif /* BEEP_H_ */

我们先了解一下音乐与单片机如何结合在一起的原理

 

通过这些频率取倒数,得到周期,再除以2,即得到一个音调高电平持续的时间。 

下面是一些表格计算的周期时间:

 有了这些数据,我们便可以使用数组来存储这些值。


有关音乐的知识在这里就不再写了,大家可以百度上去查看,

最重要的是   音调加节奏     

节奏就是一个音持续多长时间,这里我可以先简单说一下,

4分音符     8分音符      16分音符        2分音符

一般我们是以4分音符为标准,假如让它的时值为1,

那么2分音符就是它的时值的两倍。

8分音符的时值就是它的1/2。

16分音符的时值就是它的1/4.

这样每个音持续的时间我们也可以用一个1数组存起来。

下面我们以一闪一闪亮晶晶这首歌为例子

4/4表示的是以四份音符为一拍,每小节四拍

比如  1   1   5    5    都是四分音符,刚好四个合在一起为4拍。

—表示的声音的延长,如果与5结合的话,表示的是两拍。所以我们把四分音符定义为2的速度的··话,5-表示的四

 下图所示即我们的音乐

Uint16 Song[]={1,1,5,5,6,6,5,4,4,3,3,2,2,1,5,5,4,4,3,3,2,5,5,4,4,3,3,2,22}; //一闪一闪亮晶晶


Uint16 DT[]  ={2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4};      //节拍

我们课设的第三个任务是音乐的音调对应不同的灯,我们又写了一个函数,LEDx_TOGGLE表示的是LED翻转,我们通过a来控制

void ledSelect(int a)
{
    switch(a)
    {
        case 0: LED1_TOGGLE; break;
        case 1: LED2_TOGGLE; break;
        case 2: LED3_TOGGLE; break;
        case 3: LED4_TOGGLE; break;
        case 4: LED5_TOGGLE; break;
        case 5: LED6_TOGGLE; break;
        case 6: LED7_TOGGLE; break;
    }
}

最后是与这句话连接在一起的,song是我们前面创建的歌曲的音调数组,addr从0开始,比如song[0]=1, 1+1=2,  2%7=2,    2-对应第三盏LED灯亮 也就是

 do--3

 re--4

mi--5

fa--6

sol-7

la--1

xi--2

ledSelect((Song[addr]+1) % 7);
addr++;

main.c如下 

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File

#include "leds.h"
#include "key.h"


/*******************************************************************************
* 函 数 名         : main
* 函数功能         : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File

#include "leds.h"
#include "beep.h"
Uint16 Musi[23]={       //单位us,不同频率下,不同声调的声音
                0,      //静止符
                3816,   //L_do
                3496,   //L_re
                3215,   //L_mi
                2865,   //L_fa
                2551,   //L_so
                2272,   //L_la
                2024,   //L_xi
                1912,   //do
                1703,   //re
                1517,   //mi
                1432,   //fa
                1275,   //so
                1136,   //la
                1013,   //xi
                956,    //H_do
                851,    //H_re
                758,    //H_mi
                716,    //H_fa
                638,    //H_so
                568,    //H_la
                506,    //H_xi
                0xFF    //STOP
                };

//Uint16 Song[]={1,1,5,5,6,6,5,4,4,3,3,2,2,1,5,5,4,4,3,3,2,5,5,4,4,3,3,2,22}; //一闪一闪亮晶晶
//Uint16 DT[]  ={2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4};      //节拍



//Uint16 Song[]={5,5,6,5,8,7,5,5,6,5,8,7,5,5,5,10,8,7,6,11,10,8,9,8,22};    //祝你生日快乐
//Uint16 DT[]  ={2,2,5,4,6,8,2,2,5,6,6,9,4,2,5,4,6,12,2,2,5,6,8,12 };           //节拍

Uint16 Song[]={15,16,13,15,12,19,21,20,19,17,19,16,16,17,14,13,
               12,13,15,16,10,15,13,12,13,15,12,17,19,14,16,13,
               15,12,10,12,10,12,13,14,16,13,12,13,15,16,19,17,
               16,17,16,15,13,12,10,10,15,13,15,13,12,10,12,13,
               15,12,22};                                                   //梁祝
Uint16 DT[]  ={3,1,1,1,2,3,1,1,1,1,1,4,3,1,2,2,
               3,1,2,2,2,2,1,1,1,1,4,3,1,2,2,1,
               1,4,1,2,2,1,1,1,1,4,1,1,3,1,2,2,
               2,1,1,2,1,1,2,4,4,3,1,1,1,1,1,1,
               1,4};                                                        //节拍

Uint32 gain = 600000;//以600ms为一个四分音符的节拍,

void ledSelect(int a)
{
    switch(a)
    {
        case 0: LED1_TOGGLE; break;
        case 1: LED2_TOGGLE; break;
        case 2: LED3_TOGGLE; break;
        case 3: LED4_TOGGLE; break;
        case 4: LED5_TOGGLE; break;
        case 5: LED6_TOGGLE; break;
        case 6: LED7_TOGGLE; break;
    }
}
/*******************************************************************************
* 函 数 名         : main
* 函数功能         : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main()
{
    InitSysCtrl();

    LED_Init();
    BEEP_Init();
    KEY_Init();
    while(1)
    {
        Uint16 addr = 0;
        while(1)
        {

            if(Musi[Song[addr]] == 0xFF)//如果music到了停止符,
            {
                break;//跳出循环,停止播放音乐
            }
            else
            {
                Uint32 countTime = 0;//countTime来计算时间
                ledSelect((Song[addr]+1) % 7);

                while(countTime < gain * DT[addr])//
                {
                    if(countTime % Musi[Song[addr]] == 0)
                    BEEP_TOGGLE;//蜂鸣器响
                    countTime++;
                }
                ledSelect((Song[addr]+1) % 7);
                Uint32 i = 0;
                for(i = 0;i < gain; i++);
                addr++;
            }
        }
    }
}

  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于DSP28335的PWM实现流水的代码,不包含延时函数。需要注意的是,该代码使用了DSP28335的定时器中断来实现流水效果。 ```c #include "DSP2833x_Device.h" #define PWM_PERIOD 3750 // PWM周期为15000个CPU时钟周期,即3750个PWM时钟周期(PWM时钟频率为150MHz/128 = 1.171875MHz) #define PWM_DUTY_MAX 3750 // 最大占空比为100% volatile Uint16 pwm_cnt = 0; interrupt void pwm_isr(void) { EALLOW; EPwm1Regs.ETCLR.bit.INT = 1; // 清除PWM中断标志位 EDIS; pwm_cnt++; if (pwm_cnt > 3) { pwm_cnt = 0; } switch (pwm_cnt) { case 0: EPwm1Regs.CMPA.half.CMPA = PWM_DUTY_MAX; // PWM1输出高电平 EPwm2Regs.CMPA.half.CMPA = 0; // PWM2输出低电平 EPwm3Regs.CMPA.half.CMPA = 0; // PWM3输出低电平 break; case 1: EPwm1Regs.CMPA.half.CMPA = 0; // PWM1输出低电平 EPwm2Regs.CMPA.half.CMPA = PWM_DUTY_MAX; // PWM2输出高电平 EPwm3Regs.CMPA.half.CMPA = 0; // PWM3输出低电平 break; case 2: EPwm1Regs.CMPA.half.CMPA = 0; // PWM1输出低电平 EPwm2Regs.CMPA.half.CMPA = 0; // PWM2输出低电平 EPwm3Regs.CMPA.half.CMPA = PWM_DUTY_MAX; // PWM3输出高电平 break; case 3: EPwm1Regs.CMPA.half.CMPA = 0; // PWM1输出低电平 EPwm2Regs.CMPA.half.CMPA = PWM_DUTY_MAX; // PWM2输出高电平 EPwm3Regs.CMPA.half.CMPA = 0; // PWM3输出低电平 break; default: break; } } void main(void) { InitSysCtrl(); // 系统时钟初始化 InitPieCtrl(); // 中断初始化 IER = 0x0000; // 禁止所有中断 IFR = 0x0000; // 清除所有中断标志位 InitPieVectTable(); // 初始化PIE向量表 EALLOW; PieVectTable.EPWM1_INT = &pwm_isr; // 将PWM中断函数指针注册到PIE向量表 EDIS; // PWM1初始化 EPwm1Regs.TBPRD = PWM_PERIOD; // PWM周期 EPwm1Regs.TBCTL.bit.CTRMODE = 0x00; // 增计数模式 EPwm1Regs.TBCTL.bit.PHSEN = 0x00; // 不使用相位补偿 EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x00; // 高速时钟分频系数为1 EPwm1Regs.TBCTL.bit.CLKDIV = 0x07; // 低速时钟分频系数为128 EPwm1Regs.CMPA.half.CMPA = 0; // PWM初始占空比为0% EPwm1Regs.AQCTLA.bit.CAU = 0x02; // 当计数器计数到CMPA时,PWM输出高电平 EPwm1Regs.AQCTLA.bit.CAD = 0x01; // 当计数器计数到CMPA时,PWM输出低电平 // PWM2初始化 EPwm2Regs.TBPRD = PWM_PERIOD; // PWM周期 EPwm2Regs.TBCTL.bit.CTRMODE = 0x00; // 增计数模式 EPwm2Regs.TBCTL.bit.PHSEN = 0x00; // 不使用相位补偿 EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0x00; // 高速时钟分频系数为1 EPwm2Regs.TBCTL.bit.CLKDIV = 0x07; // 低速时钟分频系数为128 EPwm2Regs.CMPA.half.CMPA = 0; // PWM初始占空比为0% EPwm2Regs.AQCTLA.bit.CAU = 0x02; // 当计数器计数到CMPA时,PWM输出高电平 EPwm2Regs.AQCTLA.bit.CAD = 0x01; // 当计数器计数到CMPA时,PWM输出低电平 // PWM3初始化 EPwm3Regs.TBPRD = PWM_PERIOD; // PWM周期 EPwm3Regs.TBCTL.bit.CTRMODE = 0x00; // 增计数模式 EPwm3Regs.TBCTL.bit.PHSEN = 0x00; // 不使用相位补偿 EPwm3Regs.TBCTL.bit.HSPCLKDIV = 0x00; // 高速时钟分频系数为1 EPwm3Regs.TBCTL.bit.CLKDIV = 0x07; // 低速时钟分频系数为128 EPwm3Regs.CMPA.half.CMPA = 0; // PWM初始占空比为0% EPwm3Regs.AQCTLA.bit.CAU = 0x02; // 当计数器计数到CMPA时,PWM输出高电平 EPwm3Regs.AQCTLA.bit.CAD = 0x01; // 当计数器计数到CMPA时,PWM输出低电平 EALLOW; PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // 使能PWM中断 EDIS; IER |= M_INT3; // 使能PIE中断 EINT; // 全局中断使能 while (1); } ``` 该代码中,通过三个EPWM模块分别控制三个LED,其中每个PWM模块的输出占空比在ISR中进行置,以实现流水效果。在main函数中,通过使能PWM中断和PIE中断,来启用PWM输出和中断服务程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值