单片机学习————单片机基础与流水灯及蜂鸣器

认识单片机

在一片集成电路芯片上集成微处理器CPU、存储器、I/O接口电路,从而构成了单芯片微型计算机,即单片机。

电平特性

数字电路中只有两种电平:高电平和低电平
高电平:5V或者3.3V,取决单片机电源。
低电平:0V
RS232电平:计算机串口的电平
高电平:-12V
低电平:+12V
注:单片机IO口默认输出高电平

单片机工作时序

 (1) 振荡周期: 也称时钟周期, 是指为单片机提供时钟脉冲信号的振荡源的周期,我们开发板上为12MHZ。 
 (2) 状态周期: 每个状态周期为时钟周期的 2 倍, 是振荡周期经二分频后得到的。 
 (3) 机器周期: 一个机器周期包含 6 个状态周期S1~S6, 也就是 12 个时钟(振荡)周期。 在一个机器周期内, CPU可以完成一个独立的操作。 
 (4) 指令周期: 它是指CPU完成一条操作所需的全部时间。 每条指令执行时间都是有一个或几个机器周期组成。MCS - 51 系统中, 有单周期指令、双周期指令和四周期指令

点亮LED

原理

LED的工作是有方向性的,只有当正级接到LED阳极,负极接到LED的阴极的时候才能工作,如果反接LED是不能正常工作的。

单片机LED原理如下图,LED的阳极串联一个电阻,然后连接到电源VCC,而LED的阴极连接到单片机的P20口,要点亮一盏LED就对把单片机相对应的IO赋为低电平,则对于IO口为阴极,LED就可点亮。
单片机学习————单片机基础与流水灯及蜂鸣器_第1张图片

程序

#include   
sbit led=P2^0;  
   
int main()  
{  
    while(1)  
    {  
        led=0;        
    }         
} 

点流水灯

左右移函数
crol(a,b);循环左移函数,a是左移的值,b是左移的位数。包含在instrins.h库函数里面。
cror(a,b);循环右移函数,a是右移的值,b是右移的位数。包含在instrins.h库函数里面。

P20口点亮表示为0xfe 即1111 1110 此时p1-7口为1,也就是1-7口高电平,led不亮,只有p20口为低电平p20亮。 要实现流水灯即将0不断左移到7口时再不断右移以此循
环。

程序

#include 
#include   
#define led P2

int delay(int i)
{
	while(i--);
}
int main()
{
	int i;
	led=0xfe;  //1111 1110
	delay(50000);
	while(1)
	{
		for(i=0;i<7;i++)
		{
		   led=_crol_(led,1);
		   delay(50000);
		}
		for(i=0;i<7;i++)
		{
		   led=_cror_(led,1);
		   delay(50000);
		}
	}

}

认识蜂鸣器

电磁式蜂鸣器(有源蜂鸣器)由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

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

控制蜂鸣器

1.改变单片机引脚输出波形的频率,就可以调整控制蜂鸣器音调,产生各种不同音色、音调的声音。
2.改变输出电平的高低电平占空比(一个高电平所占时间与周期之比),则可以控制蜂鸣器的声音大小。

电路原理图

单片机学习————单片机基础与流水灯及蜂鸣器_第2张图片

单片机学习————单片机基础与流水灯及蜂鸣器_第3张图片

#include
sbit beep=P1^5;//beep表示蜂鸣器
int delay(int i)
{
	while(i--);
}

int main()
{
	while(1)
	{
		beep=~beep;//取反,让高低电平不断产生
		delay(100);//得到一定频率的脉冲,以此驱动无源蜂鸣器
	}
}

蜂鸣器进阶----演奏音乐

注:建议学习了定时器后再看这部分

单片机产生音乐的原理:
音乐的产生主要是通过单片机的I/O口输出高低不同的脉冲信号来控制蜂鸣器发音,要想产生音频脉冲信号,需要算出某音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半周期的时间,每当计时到后就输出脉冲的I/O口反相,这样就在此I/O口上得到此脉冲的频率。
通常,利用单片机的内部定时器0,工作在方式一下,改变计数初始值TH0和TL0来产生不同的率。
例如,若单片机采用12MHzs晶振,要产生频率为587Hzs的音频脉冲时,其音频信号的脉冲周期T=1/587=1703.5775us,半周期时间为852us,因此总要令计时器计数=852us/1us=852,在每计数852时将I/O口反相,就得到C大调的中调Re。
由于定时器0的在方式一计数方式为16位计数器,最多只能装载的数为2的16次方即65536个,也就是说定时器计数到65536就会进入中断函数,而在中断函数中将输出脉冲的I/O口反相即可,故只需设置好定时器0的初值就可以了发出特定的音频了

#include 
#define RldTmr(fr) 65536 - (11059200 / 12) / (fr << 1)
#define FuDian(n) (n << 1) / 3    //附点n分音符的换算
 
typedef unsigned char UCHAR;
typedef unsigned int UINT;
typedef unsigned long ULONG;
 
sbit BUZZ = P1^5;
 
UINT code noteFreq[] = {    //中音 1-7 和高音 1-7对应的频率列表
    523, 587, 659, 698, 784, 880, 988,
    1047, 1175, 1319, 1397, 1568, 1760, 1976
};
UINT code tmrRld[] = {      //中音 1-7 和高音 1-7对应的定时器重载值
    RldTmr(523), RldTmr(587), RldTmr(659), RldTmr(698), RldTmr(784), RldTmr(880), RldTmr(988),
    RldTmr(1047), RldTmr(1175), RldTmr(1319), RldTmr(1397), RldTmr(1568), RldTmr(1760), RldTmr(1976),
};
UCHAR code musicNote[] = {      //音名
    1, 2, 3, 1,
    1, 2, 3, 1,
    3, 4, 5,
    3, 4, 5,
    5, 6, 5, 4, 3, 1,
    5, 6, 5, 4, 3, 1,
    1, 5, 1,
    1, 5, 1
};
UCHAR code noteDuration[] = {       //音名对应的时值,4表示4分音符,8表示8分音符,16表示16分音符
    4, 4, 4, 4,
    4, 4, 4, 4,
    4, 4, 2,
    4, 4, 2,
    FuDian(8), 16, FuDian(8), 16, 4, 4,
    FuDian(8), 16, FuDian(8), 16, 4, 4,
    4, 4, 2,
    4, 4, 2
};
bit enable = 1, tmrFlg = 0;
UCHAR T0RH = 0XFF, T0RL = 0X00;
 
void Delay(UINT n);
void PlayMusic(UCHAR speed);    //固定标准为4分音符的速度:例如speed = 108 表示一分钟扫过108个4分音符
 
void main() {
    EA = 1;
    TMOD = 0X01;
    TH0 = T0RH;
    TL0 = T0RL;
    ET0 = 1;
    TR0 = 1;
    while (1) {
        PlayMusic(72);
        Delay(40000u);
    }
}
 
void Delay(UINT n) {
    UINT i;
    for (i = 0; i < n; i++) ;
}
 
void PlayMusic(UCHAR speed) {
    UCHAR i;
    UCHAR idx;
    UINT cnt = 0;
    UINT durationCnt = 0;	//当前音符的时值对应的定时器计数
    UINT soundCnt = 0;		//当前音符的发声时值对应的计数值
    for (i = 0; i < sizeof (musicNote); ) {
        while (!tmrFlg) ;
        tmrFlg = 0;
        if (cnt == 0) {
            idx = musicNote[i] - 1;
            T0RH = tmrRld[idx] >> 8;
            T0RL = tmrRld[idx];
            durationCnt = (ULONG)240 * (ULONG)noteFreq[idx] / ((ULONG)noteDuration[i] * (ULONG)speed);
            soundCnt = durationCnt - (durationCnt >> 2);	//当前音符时值的前3/4发声,后1/4静音
            enable = 1;
            cnt++;
        }
        else {
            if (cnt == durationCnt) {
                cnt = 0;
                i++;
            }
            else {
                cnt++;
                if (cnt == soundCnt) {
                    enable = 0;
                }
            }
        }
    }
}
 
void InterruptTmr0() interrupt 1 {
    TH0 = T0RH;
    TL0 = T0RL;
    tmrFlg = 1;
    if (enable)
        BUZZ = ~BUZZ;
    else
        BUZZ = 1;
}

你可能感兴趣的:(单片机学习————单片机基础与流水灯及蜂鸣器)