赞
踩
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。