zoukankan      html  css  js  c++  java
  • C51模拟I2C,音乐播放(记忆)

    #include <reg52.h>
    #include <intrins.h>
    
    
    #define	SA	(1 << 7)	
    #define	SB	(1 << 6)	
    #define	SC	(1 << 5)	
    #define	SD	(1 << 4)	
    #define	SE	(1 << 3)	
    #define	SF	(1 << 2)	
    #define	SG	(1 << 1)
    #define	SH	(1 << 0)
    
    typedef unsigned char uchar;
    typedef unsigned int uint;
    
    
    //led
    const uchar LEDData[] =
    {
    	SA |SB |SC | SD |SE |SF,		//0
    	SB |SC,						//01
    	SA |SB |SG | SE | SD,			//02
    	SA |SB |SC | SD | SG,			//03
    	SB |SF | SG | SC,				//04
    	SA |SF | SG |SC  | SD,		//05
    	SA |SC |SD | SE | SG | SF,		//06
    	SA | SB|SC,					//07
    	SA |SB |SC | SD | SE | SF | SG,//08
    	SA |SB |SC|SD | SF | SG	,	//09
    	0,							//mask - 10	
    	SG,							//minus - 11	
    	SA |SB | SE | SF | SG			//P - 12			
    };
    
    sbit	music_note		= 	P0	^	0;
    sbit	music_beat		=	P0	^	1;
    sbit	music_time		=	P0	^	2;
    sbit	starting_up		=	P0	^	3;
    
    
    //music
    sbit  speaker=P0 ^ 4;  
    uchar byteTH0,byteTL0,smg_num,step,mutex;
    // 小星星句子,三个一组,第一个表示音符,第二个表示音阶,第三个表示延时长度(单位约等于0.1s)
    code uchar music[]={      
     1,2,2, 1,2,2, 5,2,2, 5,2,2, 6,2,2, 6,2,2, 5,2,4,
     4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,2, 2,2,2, 1,2,4,
     5,2,2, 5,2,2, 4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,4,
     5,2,2, 5,2,2, 4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,4,
     1,2,2, 1,2,2, 5,2,2, 5,2,2, 6,2,2,  6,2,2, 5,2,4,
     4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,2, 2,2,2, 1,2,4 };
    
    //定时器计时初值,高八位,代表不同音符的频率
    code uchar FREQH[]={
     0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 
     0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,
     0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
     0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,} ;
    
    //定时器计时初值,低八位,代表不同音符的频率
    code uchar FREQL[]={
     0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
     0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,
     0x8F,0xEE,0x44, 0x6B,0xB4,0xF4,0x2D, 
     0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,};
    
    
    //i2c
    void delay();
    void start();
    void stop();
    void ack();
    void no_ack();
    void i2c_write_byte(uchar dat);
    uchar i2c_read_byte();
    void init_i2c();
    void delay_long();
    void write_byte(uchar add, uchar dat);
    uchar read_byte(uchar add);
    void total_shutdown();
    
    //music
    void song_beat(uchar duration);
    void delay_music(unsigned char t);
    void init_music();//设定定时/计数器工作在方式1,16位模式,计数溢出就产生中断,数码管显示音符
    void song();
    void music_show();
    
    
    sbit sda = P0 ^ 5;
    sbit scl = P0 ^ 6;
    
    
    void main()
    {
    
    	//total_shutdown();
    	/////////////////////////////////////////
    	song();
    
    }
    
    											  
    
    //定时器0的中断服务程序,蜂鸣器反向,设定新的定时时间,启动定时,数码管显示音符
    void timer0() interrupt 1
    {
    	TR0=0;
    	speaker=!speaker;	
    	P2 = ~LEDData[music[step]];
    	music_note = !music_note;
       	/*
    	P2 = 0x55;
    	music_beat = !music_beat;
    	 */
    	TH0 = byteTH0;
    	TL0 = byteTL0;
    	TR0=1;
    }
    
    
    
    void delay_music(uchar t)
    {
    	uint i;
    	uchar j=80;
    	for(i=0; i<t*100; i++)
    		while(j--);
        TR0=0;
    }
    
    void song_beat(uchar duration)
    {
    	TH0 = byteTH0;
    	TL0 = byteTL0;
    	TR0 = 1;
    	delay_music(duration);                       
    }
    
    //设定定时/计数器0工作在方式1,16位模式,计数溢出就产生中断
    void init_music()
    {
    	TMOD |= 0x01;
    	EA=1;
    	ET0=1;
    }
    
    void song()
    {
    	uchar dura,index;
    	init_music();
    	while(1)
        {
    		//step=0;  
    		step = read_byte(10);
    		while(step<126)
    		{
    			//在该音符音阶下需要鸣唱的时间
    			index = music[step] + 7 * music[step+1] - 1;
    			byteTH0 = FREQH[index];
    		    byteTL0 = FREQL[index];
    			//
    		    dura = music[step+2];
    		    step += 3;
    		    song_beat(dura);
    			if(step >= 126)
    			{
    				step = 0;
    			}
    			//i2c读写之间需要一点时间间隔
    			write_byte(10,step);
    		}
    		delay_music(10);
    	} 	
    }
    
    void delay()
    {
    	_nop_();
    	_nop_();
    	_nop_();
    	_nop_();
    	_nop_();
    	_nop_();
    	_nop_();
    	_nop_();
    }
    
    void start()
    {
    	sda = 1;
    	delay();
    	scl = 1;
    	delay();
    	sda = 0;
    	delay();
    }
    
    void stop()
    {
    	sda = 0;
    	delay();
    	scl = 1;
    	delay();
    	sda = 1;
    	delay();
    }
    
    void ack()
    {
    	uchar i;
    	scl = 1;
    	delay();
    	while(sda == 1 && i < 200)
    	{
    		i++;
    	}
    	scl = 0;
    	delay();
    }
    
    void no_ack()
    {
    	sda = 1;
    	delay();
    	scl = 1;
    	delay();
    	scl = 0;
    	delay();
    }
    
    
    void i2c_write_byte(uchar dat)
    {
    	uchar i;
    	scl = 0;
    	for(i = 0; i < 8; i++)	
    	{
    		if(dat & 0x80)
    		{
    			sda = 1;
    		}
    		else
    		{
    			sda = 0;
    		}
    		dat = dat << 1;
    		delay();
    		scl = 1;
    		delay();
    		scl = 0;
    		delay();
    	}
    	sda = 1;
    	delay();
    }
    
    uchar i2c_read_byte()
    {
    	uchar i,dat;
    	scl = 0;
    	delay();
    	sda = 1;
    	delay();
    	for(i = 0; i < 8; i++)
    	{
    		scl = 1;
    		delay();
    		dat = dat << 1;
    		if(sda == 1)
    		{
    			dat++;
    		}
    		scl = 0;
    		delay();
    	}
    	return dat;	
    }
    
    void init_i2c()
    {
    	sda = 1;
    	scl = 1;
    }
    
    
    void delay_long()
    {
    	uint i = 10000;
    	while(i--);
    }
    
    void write_byte(uchar add, uchar dat)
    {
    	init_i2c();
    	start();
    	i2c_write_byte(0xa0);	
    	ack();
    	i2c_write_byte(add);
    	ack();
    	i2c_write_byte(dat);
    	ack();
    	stop();	
    }
    
    uchar read_byte(uchar add)
    {
    	uchar dat;
    	init_i2c();
    	start();
    	i2c_write_byte(0xa0);
    	ack();
    	i2c_write_byte(add);
    	ack();
    	start();
    	i2c_write_byte(0xa1);
    	ack();
    	dat = i2c_read_byte();
    	no_ack();
    	stop();
    	return dat;
    }
    
    
    void total_shutdown()
    {
    	uchar count;
    	count = read_byte(10);
    	starting_up = 0;
    	P2 = ~LEDData[count];
    	count++;
    	if(count == 10)
    		count = 0;
    	write_byte(10,count);	
    }
    
  • 相关阅读:
    android获得屏幕高度和宽度
    Android中RelativeLayout各个属性的含义
    Android JNI知识简介
    Android结束进程方法
    android开发中的图片资源问题
    android framework下public.xml中添加资源问题
    I'm back
    test,exec,match,replace方法区别 正则
    fiddler抓包工具 https抓取 ios手机端抓取
    前端优化方案
  • 原文地址:https://www.cnblogs.com/steady/p/1905040.html
Copyright © 2011-2022 走看看