exynos4412开发板模拟小星星

 模拟小星星音乐播放

小星星

pwm_muisc_pro-----main.c

#include"exynos_4412.h"
#include"uart.h"

//pwm 模拟小星星播放

volatile unsigned int count = 0;//毫秒级变量

//延时  ms
void delay(unsigned short ms){

    unsigned int tmp = count;//存放刚进入delay函数时 count 的数值

    // while(count <= tmp+ms);//这种算法没有规避溢出问题

    while(count-tmp < ms);//这种算法规避了溢出问题,不必纠结算法,用就完事了

}


//中断初始化
exit_init(){

    //GIC 面向中断源
    //开启总中断
    ICDDCR = 1;

    //配置端口中断使能
    //中断模式:  wdt中断 id 75
    //75/32=2   75%32=11
    ICDISER.ICDISER2 |= 1<<11;

    //配置端口优先级 优先级设置为5
    //75/4= 18    75%4=3  ----  [15:8]
    ICDIPR.ICDIPR18 = (ICDIPR.ICDIPR18 & ~(0xff<<24)) | (5<<24);

    //配置中断源送去哪个cpu处理 0x1表示直送cpu0
    //寄存器分步格局 与ICDIPR 完全一样 
    ICDIPTR.ICDIPTR18 = (ICDIPTR.ICDIPTR18 & ~(0xff<<24)) | (0x1<<24);
    
    //GIC 面向cpu
    //cpu响应中断使能  =1 使能  =0 不使能
    CPU0.ICCICR = 1;

    //配置cpu过滤优先级
    CPU0.ICCPMR = 255;

}

//中断响应,c语言入口函数,在汇编汇总调用,当irq异常触发时
void do_irq(){
    //获取中断号
    int id = CPU0.ICCIAR;

    //根据中断id来处理对应的事件
    switch(id){
        case 75:

        count++;

        //先清除中断 源头的挂起 看门狗的中断
        //写入任何值清除
        WDT.WTCLRINT = 8;

        //在清除GIC分配器层中断挂起 与ICDISER_CPU 结构一样 id:57
        //置为1  清除
        ICDICPR.ICDICPR2 |= 1<<11;

        break;

    }

    //最后清除cpu中断挂起
    //写入中断id清除对应中断挂起
    CPU0.ICCEOIR = id;

}

//看门狗初始化
void dog_init(){
    //预分频
    WDT.WTCON = (WDT.WTCON &~(0xff<<8)) | (24<<8);
    //固定分频
    WDT.WTCON = (WDT.WTCON &~(0x3<<3)) | (0<<3);
    //触发中断信号  [2] 时间到,是否触发中断信号  = 1 触发中断 
    WDT.WTCON |= 1<<2;

    //重载寄存器
    WDT.WTDAT = 250;
    //计数寄存器
    WDT.WTCNT =250;

    //开启看门狗
    WDT.WTCON |= 1<<5;
}

//pwm 初始化
void pwm_init(){

    //配置GPD0_0 为pwm功能
    GPD0.CON = (GPD0.CON & ~(0xf<<0)) | (2<<0);

    //配置pwm控制器,五路固定分频 TCFG1 [3:0] = 0  这里设不固定分频
    PWM.TCFG1 &= ~(0xf);

    //频率 =  总线时钟 /固定分频/ (分频值+1) / 重载值 ;
    //两路预分频 TCFG0 [7:0] = 99  100M/(99+1) = 1M
    PWM.TCFG0 = (PWM.TCFG0 & ~(0xff<<0)) | (99<<0);

    //重载值
    PWM.TCNTB0 = 2000;
    //比较寄存器  占空比 = 比较寄存器/重载值
    PWM.TCMPB0 = 1000;

    //配置总控
    //不使能死区
    PWM.TCON &= ~(1<<4);
    //自动重装
    PWM.TCON |= 1<<3;
    //打开输出
    PWM.TCON |= 1<<2;
    //装载TCNTB0  TCMPB0
    PWM.TCON |= 1<<1;
    //关闭装载
    PWM.TCON &= ~(1<<1);

}

//启动pwm
void pwm_start(){
    //启动pwm
    PWM.TCON |= 1;
}

//关闭pwm
void pwm_stop(){
    //启动pwm
    PWM.TCON &= ~1;
}

//改变音色
void chanage_pinlv(unsigned int hz){

    if(hz == 0) //做 除数为0 校验
	{
		pwm_stop();
		return ;
	}

    //重载值
    PWM.TCNTB0 = 1000000/hz;
    //比较寄存器 //占空比我们设为50%
    PWM.TCMPB0 = 1000000/hz/2;

    //装载TCNTB0  TCMPB0
    PWM.TCON |= 1<<1;
    //关闭装载
    PWM.TCON &= ~(1<<1);
    //打开pwm
    pwm_start(); //因为我们在播放音律函数时 停止了pwm 所以每次改变音色 都要重新开启pwm
}

//定义音符频率
#define H1  1046
#define H2  1175
#define H3  1318
#define H4  1397
#define H5  1568
#define H6  1760
#define H7  1976
#define ST  0

//定义乐谱二维数组 n行两列
//这里解释为什么用const 因为数组的初始化需要memset内存复制完成,但是我们时arm逻辑变成,没有系统库
//使用const可以保证数组时常量,就不需要内存赋值操作了
//这里的 1 表示我们 一个音 要发 多久声响 在播放器中可以利用延时函数来配合完成 利用整体乘一个数来达到延时效果
const unsigned int little_star[][2] = {
    {H1, 1},{H1, 1},{H5,1},{H5,1},
	{H6, 1},{H6, 1},{H5,1},{ST,1},
	{H4, 1},{H4, 1},{H3,1},{H3,1},
	{H2, 1},{H2, 1},{H1,1},{ST,1},

	{H5, 1},{H5, 1},{H4,1},{H4,1},
	{H3, 1},{H3, 1},{H2,1},{ST,1},
    {H5, 1},{H5, 1},{H4,1},{H4,1},
	{H3, 1},{H3, 1},{H2,1},{ST,1},

    {H1, 1},{H1, 1},{H5,1},{H5,1},
	{H6, 1},{H6, 1},{H5,1},{ST,1},
    {H4, 1},{H4, 1},{H3,1},{H3,1},
	{H2, 1},{H2, 1},{H1,1},{ST,1},
	{0,0}// 结束符号
};

//播放音律
void play(const unsigned int little_star[][2]){
    unsigned int i=0;
    for( ;little_star[i][1]!=0;i++ ){
        chanage_pinlv(little_star[i][0]);
        delay(little_star[i][1]*500);//发声200毫秒
        pwm_stop();//停止
        delay(20);//停止10毫秒
    }
    
}

int main()
{
    uart_init();
    printf("music!!!\r\n");
    //看门狗初始化
    dog_init();
    //中断初始化
    exit_init();
    //pwm初始化
    pwm_init();
    //开启pwm
    pwm_start();

    int i=0;

    while(1){
        play(little_star);
        delay(2000);//所有音律播放完成总体停2秒
    }

    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值