挣扎了半天还是决定要总结一下我的单片机学习之旅!就从最基础的开始说起8,中途也会掺杂一些小项目,慢慢更~
废话不多说,直接开始8
目录
点亮第一个led灯
led的工作原理
led灯工作是具有方向性的,只有当电源正极接到led的阳极,负极接到led的阴极的情况下,led才能正常工作。
开发板上的原理图
如图,led的阳极串联一个电阻,然后连接到电源VCC,其阴极连接到单片机的P2口,若想点亮一盏led,则需将单片机对应的IO口赋为低电平。
由该原理图可得,led的阳极直接连接到电源VCC,阴极串联了一个电阻(限流。因为led有正常的工作电压与电流,若直接通过VCC 流入led,可能会使led被击穿)然后连接到单片机的IO口,D1–D8分别连接到单片机的P20–P27口,也就是说这8个led都可以通过P2口来控制。
注:因为发光二极管与限流电阻是串联的关系,若二极管仅作发光使用,则限流电阻不管接在二极管的正端还是负端,电路上的电流都是一样的;若二极管的端电压对电路其他部分有影响,则需按电压要求连接。
以使D1发光为例:根据led工作原理,电源的正极应当接到led的阳极,同时阴极须与“负极”连接到一起,即让单片机的P20口为低电平。
源程序–点亮D1:
#include "reg52.h"
sbit led=P2^0;
void main()
{
while(1)
{
led=0;//P20口给低电平,点亮D1
}
}
led闪烁
C语言常用的预处理命令1
#typedef 的使用(以下重定义针对keil编译环境)
typedef unsigned char u8;
(将unsigned char 用u8代替;假设用u8表示8位–>1个字节;unsigned char为1个字节,二者一致)
typedef unsigned int u16;
(将unsigned int 用u16代替;假设用u16表示16位–>2个字节;unsigned int为2个字节,二者一致)
重新定义一些常用的关键词,增强程序的可一致性,因为在不同编译软件上,C语言的数据类型的关键词位宽是不一样的。
while()循环函数
while(1)
{
led=0;
}
此时while循环为一个死循环,即一直会循环执行led=0这条语句,由于循环判断的时间太短,肉眼无法察觉,故看到的现象则是 led一直被点亮。
delay()延时函数
延时函数即占用CPU的时间:CPU执行一条一条的语句时,当执行到某处,让其不断的循环该处的语句,使其无法执行后面的语句,以达到延时的效果。
void delay(u16 i)
{
while(i--);
}
当i=1时,也就是该循坏只执行1次,大约是10us的时间,该时间不准确;若要准确,可使用定时器。
源程序–使D1闪烁:
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
sbit led=P2^0;
void delay(u16 i)
{
while(i--);
}
void main()
{
while(1)
{
led=0;
delay(5000);//相当于将灯点亮后 保持50ms 以便肉眼能观察到
led=1;
delay(5000);//相当于将灯熄灭后 保持50ms 以便肉眼能观察到
}
}
led流水灯
C语言常用的预处理命令2
#define 的使用
#define A P0
(程序中用A代替P0,若要改动,只需修改#define处的值)
循环左移右移函数(包含在instrins.h库函数中)
_crol_(a,b);
循环左移函数,a为左移的值,b为左移的位数。
_cror_(a,b);
循环右移函数,a为右移的值,b为右移的位数。
源程序–led流水灯:
#include "reg52.h"
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
#define led P2
void delay(u16 i)
{
while(i--);
}
void main()
{
u8 i=0;
led=0xfe; //1111 1110 即最低位--D1被点亮
delay(50000);
while(1)//死循环
{
for(i=0;i<7;i++)
{
led=_crol_(led,1);//每次左移一位
delay(50000);//若无延时,则几乎看不到现象
}
//0111 1111 已循环点亮八组led 则退出以上左移循环
for(i=0;i<7;i++)
{
led=_cror_(led,1);//每次右移一位
delay(50000);
}
}
}