https://www.keil.com/download/product/
调试51单片机需要Keil C51
,不是Keil Arm
,这两个可以安装在同一个目录下。
安装与激活过程不再赘述。
51单片机需要芯片AT89C52,创建项目的时候选中即可
#include "reg52.h"
sbit LED1=P2^0;
void main()
{
LED1=0;
while(1){
}
}
首先将 51 单片机的头文件包含进来,然后使用 sbit 关键字来定义 P2.0 管脚,定义好后即可使用 LED1 来替代 P2.0 口的操作。也就是P20。
为什么是P2^0
而不是直接用P20
,我猜是因为头文件没定义这个寄存器,而且从20到27一共就7个,用按位异或的方法就足够了。
控制台输出中有Program Size: data=9.0 xdata=0 code=19
,各项的单位都是字节:
这个函数是官方文档给的,我目前会的不多,只能先拿来用。 “使用循环来延时只是获得一个大概的时间,并不能精确,如需精确延时,后期我们会学习定时器。此处就不用纠结这个问题。”
* 函 数 名: delay_10us
* 函数功能: 延时函数,ten_us=1 时,大约延时 10us
* 输入: ten_us
* 输出: 无
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
通过 KEIL 软件仿真查看延时时间
选择“Target”选项卡,在 Xtal(MHz)文本框中输入 12M,该值表示开发板上实际使用外部晶振大小,我的开发板实际上10.9,则修改为对应值。然后点击 OK
keil界面长得比较粗糙,但不影响使用。需要按F10步过,通过对比这一语句运行前后的时间,来得到elay_10us(50000)运行的实际时间。
根据流水灯实现原理,即 IO 口由低往高或者由高往低逐个输出低电平特点,那么我们可以将移位操作以及循环结合进来。
根据原理图,端口为低电平时才能把灯点亮。
0X01<<i
表示 i增加 1 次,0x01
中的 1 就移动多少位,因为 1(高电平)不会让 LED 点亮,需要取反后变为低电平 0 才能点亮,所以最后的结果需要取反后给 LED_PORT
口,并且每次循环都要延时一段时间,这样才能分辨出来 LED 在流水。
#include "reg52.h"
#define LED_PORT P2
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void main()
{
u8 i;
while(1){
for(i=0;i<8;i++)
{
LED_PORT=~(0x01<<i);
delay_10us(50000);
}
}
}
除了使用 for 循环语句实现移位,KEIL C51 软件内还有对应的移位库函数,左移函数是_crol_()
,右移函数是_cror_()
,要使用这两个函数在我们的程序中必须包含 intrins.h
头文件。
进入 main 函数后首先定义一个变量 i,LED_PORT=~0x01
,因为 LED 是低电平点亮,所以 0X01
取反后的结果是 0XFE
,对应二进制数为 1111 1110
,即最低位为 0,因此最开始的 D1 指示灯会点亮,然后进入 while 循环,使用 for 循环、_crol_
和_cror_
移位函数实现 LED 左右流水显示。
#include "reg52.h"
#include "intrins.h"
#define LED_PORT P2
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void main()
{
u8 i;
LED_PORT=~0x01;
delay_10us(50000);
while(1)
{
for(i=0;i<7;i++)
{
LED_PORT=_crol_(LED_PORT,1);
delay_10us(50000);
}
for(i=0;i<7;i++)
{
LED_PORT=_cror_(LED_PORT,1);
delay_10us(50000);
}
}
}
我用的是厂子自己的下载器,需要修改芯片类型和文件路径。波特率高了的话,下载器会自动降下来。 芯片型号用灯照着板子,就看到了。