51蜂鸣器

1.蜂鸣器产生声音

main.c

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"

sbit Buzzer=P2^5;//看原理图找引脚
unsigned int i;
unsigned char KeyNum;

void main() 
{
	Nixie(1,0);
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
			for(i=0;i<100;i++)
			{
				Buzzer=!Buzzer;//蜂鸣器产生振动声音;只是产生一次,循环让它持续产生;
				Delay(1);//取反就是产生声音;
			}
			Nixie(1,KeyNum);
		}
	}
}

Nixie.c  数码管显示

#include <REGX52.H>
#include "Delay.h"

//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

/**
  * @brief  数码管显示
  * @param  Location 要显示的位置,范围:1~8
  * @param  Number 要显示的数字,范围:段码表索引范围
  * @retval 无
  */
void Nixie(unsigned char Location,Number)
{
	switch(Location)		//位码输出
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];	//段码输出
//	Delay(1);				//显示一段时间
//	P0=0x00;				//段码清0,消影
}

Nixie.h

#ifndef __NIXIE_H__
#define __NIXIE_H__

void Nixie(unsigned char Location,Number);

#endif

形成一个连续的音乐:主要依托定时器来完成;

main.c

思路:定义一个音乐的数组,再定义一个新的变量,让变量在while(1)中进行++,保证数组中进行递进,简单来说就是第一个音符发出声音以后,能够++  来到下一个音符,Delay进行延迟,如果需要不同音符之间产生间隙,需要TR0=0然后再置1,;

最后插入定时器中断函数,定时器的作用就是保证每过一秒中断就启动一次;将新定义的变量放进数组中,保证每次中断都能调用数组中的音符;

#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"

sbit Buzzer=P2^5;

unsigned int FreqTable[]={
63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
65058,65085,65110,65134,65157,65178,65198,65217};

unsigned char FreqSelect;
void main()
{
	Timer0_Init();
	while(1)
	{
		FreqSelect++;
		Delay(500);
		TR0=0;//每发出一个声音以后,关闭-延迟-打开,保证音符与音符之间停顿;
		Delay(5);
		TR0=1;
	}
}
void Timer0_Routine() interrupt 1  //定时器设置的是1毫秒,表示每一毫秒就会过来一次中断;
{
	TL0=FreqTable[FreqSelect]%256;  //设置定时初值
	TH0=FreqTable[FreqSelect]/256;  //设置定时初值
  Buzzer=!Buzzer;
}

2.AT24C02--数据存储芯片(I2C总线)

AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息;简单来说就是实现断电以后保存数据的功能,保证下次开机后可以直接使用;通讯接口:I2C总线;容量:256字节;

存储器分易失性存储器RAM和非易失性存储器ROM;通常用于较快的存储功能时,我们会使用RAM,需要永久保存时,我们会使用ROM;

SRAM:静态RAM;DRAM:动态RAM;

MaskROM:掩膜ROM;PROM:可编程ROM;EPROM:可擦除可编程ROM;E2PROM:电可擦除可编程ROM;Flash:闪存;硬盘、软盘、光盘;        

I2C总线是一种通用数据总线;类似于一种通讯协议;包含两根通讯线:SCL和SDA;实现多个设备进行通讯;

I2C时序结构:

起始条件:SCL高电平期间,SDA从高电平切换到低电平;

终止条件:SCL高电平期间,SDA从低电平切换到高电平;

发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上,然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节;

接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上,然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节;主机在接收之前,需要释放SDA;

发送应答:数据在接收以后会有一个发送应答;简单来说就是接收完成一个字节后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答;

接收应答:数据在发送完成以后会有一个接收应答;简单来说就是发送完成一个字节以后,主机在下一个时钟接收一位数据,数据0表示应答,数据1表示非应答;(主机在接收之前,需要释放SDA);

字节写:在WORD ADDRESS处写入数据DATE;

随机读:读出WORD ADDRESS处的数据DATE;

数据存储功能:

main.c

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Key.h"
#include "AT24C02.h"

unsigned char KeyNum;
unsigned int Num;
void main()
{
	LCD_Init();
	LCD_ShowNum(1,1,Num,5);
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Num++;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==2)
		{
			Num--;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==3)//K3按键,向AT24C02写入数据
		{
			AT24C02_WriteByte(0,Num%256);//Num%256表示低四位
			Delay(5);
			AT24C02_WriteByte(1,Num/256);
			Delay(5);
			LCD_ShowString(2,1,"Write OK");
			Delay(1000);
			LCD_ShowString(2,1,"         ");
		}
		if(KeyNum==4)//K4按键,从AT24C02写读取数据
		{
			Num=AT24C02_ReadByte(0);
			Num|=AT24C02_ReadByte(1)<<8;
			LCD_ShowNum(1,1,Num,5);
			LCD_ShowString(2,1,"Read OK");
			Delay(1000);
			LCD_ShowString(2,1,"         ");
		}
	}
}

I2C.c

#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

void I2C_Start(void)//起始条件
{
	I2C_SDA=1;//保证初始条件两个都是高的
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}
void I2C_Stop(void)//终止条件
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}
void I2C_SendByte(unsigned char Byte)//发送字节无返回值
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
	  I2C_SCL=1;
	  I2C_SCL=0;
	}
}
unsigned char I2C_ReceiveByte(void)//接收字节需要有返回值
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;//主机在接收之前,需要释放一个字节;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;//开始读取字节;
	  if(I2C_SDA){Byte|=(0x80>>i);}//如果SDA是1,开始读取,最高位置1,否则Byte初始化值为0;
	  I2C_SCL=0;//|运算符的意思就是说SCL高电平开始发送,在高电平状态下进行接收,所以置1;
	}
	return Byte;
}
void I2C_SendACK(unsigned char Sendbit)//发送字节-bit和unsigned char意义一样,不过unsigned char是8位,bit是一位;
	{//发送应答
	I2C_SDA=Sendbit;
	I2C_SCL=1; 
	I2C_SCL=0;
}
unsigned char I2C_ReceiveACK(void)//接收应答有返回值
{
	unsigned char Receivebit;
	I2C_SDA=1;//接收时SDA先释放;
	I2C_SCL=1;
	Receivebit=I2C_SDA;
	I2C_SCL=0;
	return Receivebit;
}

I2C.h

#ifndef _I2C__H_
#define _I2C__H_

void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendACK(unsigned char Sendbit);
unsigned char I2C_ReceiveACK(void);

#endif

AT24C02.c

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS     0xA0      //AT24C02的固定地址为1010,所以ADDRESS+W为0xA0,ADDRESS+R为0xA1;
void AT24C02_WriteByte(unsigned char WordAddress,Date)//字节写
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveACK();
	I2C_SendByte(WordAddress);
	I2C_ReceiveACK();
	I2C_SendByte(Date);
	I2C_ReceiveACK();
	I2C_Stop();
}
unsigned char AT24C02_ReadByte(unsigned char WordAddress)//字节读
{
	unsigned char Date;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveACK();
	I2C_SendByte(WordAddress);
	I2C_ReceiveACK();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveACK();
	Date=I2C_ReceiveByte();
	I2C_SendACK(0x01);
	I2C_Stop();
	return Date;
}

AT24C02.h

#ifndef _AT24C02__H_
#define _AT24C02__H_
void AT24C02_WriteByte(unsigned char WordAddress,Date);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);
#endif

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值