《单片机傻瓜篇》

以计算机相关专业角度学习单片机

本人为软件工程专业,接触计算机硬件学习较少,以一个嵌入式非专业角度,入门学习。对于一个要求红黑树都要能敲出来的专业,对于这种面向寄存器编程,是比较简单的,大家可以很快入门(写代码而言,想外设学习,自己组装硬件还学专业地学习电子相关知识)如有错误请见谅。使用普中51-单核-A2学习。本学习笔记适合人员:计算机相关专业、或者有熟练的C语言编程学习经历的勇士!

单片机针脚

      C51系列单片机有4*8=32个针脚。p0,p1,p2,p3四个寄存器,每个寄存器大小为8位,干什么用的呢?这些针脚只有两种状态即0(低电平)与1(高电平)。我们可以通过写程序,通过编译器生成CPU的一条条指令,烧录到里面去。我们通过对针脚的高低电平进行逻辑判断,再通过一系列状态对针脚状态做出改变。
      举一个例子,比如查看某个针脚状态,读到了1,可以假想(另一个针脚上连着电机),我们改变针脚状态,让电机转起来。
      总之完单片机编程玩的就是寄存器,我们也可以称它为针脚编程。为什么使用C语言写的呢,而写我们好像都是用的一个叫做keil的软件。其实我们的C语言代码没有跑在单片机上,CPU认识的东西叫做指令集,其实就是一串串0-1编码。一条条执行,跑了起来,keil就是做其中的转换的一个编译软件,将我们写的C语言单片机代码转换为CPU可以认识的一条条指令。有人肯定想问:我们不用C语言不行吗,当然可以,如果你能写一个自己的编程语言,做这样的转换,也许下一个革命的人就是你呢。
在这里插入图片描述

那个银亮色的晶振什么鬼

      人们都说单片机的心藏是那个叫晶振的东西,晶振有什么用呢。上面我们提到,CPU认识需要执行一条一条的指令,但机器怎么知道一条条执行呢,我们可以傻瓜式想想,晶振发出脉冲信号,没发一次单片机就会执行一条或多条指令。我们后面会学到单片的中断、定时器,晶振每隔固定时间发出信号,那么我们就可以利用它来知道经过了多长时间。管它什么鬼呢,把硬件交给搞硬件的,我们先专心写我们的面向针脚编程吧。

C51程序界的Hello World
#include <REGX52.H>

void main()
{
	P2=0xFE;	//1111 1110
	while(1)
	{
		
	}
}

      我们通过控制寄存器存储的值,来改变针脚的状态,后面为什么有一个while(1){}呢,单片机程序与我们现在windows、Linux C程序不同,电脑上的程序运行一次就结束了。单片机如果程序运行完后、它会从头再来。所以我们让单片机卡死在哪里就好了。

LED灯闪烁实现

      怎样实现延时呢?没错我们可以暴力解决,让它运行一段循环不就行了嘛。我们可以使用stc-isp软件来生成延时代码片段。我们要知道,晶振就像一个定时的东西,每隔一个固定的时间片段就会发出脉冲信号,让我们的单片机CPU指令,一条条执行(形象地描述,原理太复杂了,恐怕要读一整本计算机组成原理)

#include <REGX52.H>
#include <INTRINS.H>

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
	while(1)
	{
		P2=0xFE;	//1111 1110
		Delay500ms();
		P2=0xFF;	//1111 1111
		Delay500ms();
	}
}

      我们改变的个针脚的状态,交替执行,转态变化 0__1__0__1__0__1…,这样不就闪烁起来了吗。

LED流水灯实现

      流水灯这不过,是一排灯按照按顺序点亮,灭掉,下一个点亮,灭掉…而已。我们按一定的逻辑来控制一个寄存器的位的状态就好了。

#include <REGX52.H>
#include <INTRINS.H>

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
	while(1)
	{
		P2=0xFE;//1111 1110
		Delay500ms();
		P2=0xFD;//1111 1101
		Delay500ms();
		P2=0xFB;//1111 1011
		Delay500ms();
		P2=0xF7;//1111 0111
		Delay500ms();
		P2=0xEF;//1110 1111
		Delay500ms();
		P2=0xDF;//1101 1111
		Delay500ms();
		P2=0xBF;//1011 1111
		Delay500ms();
		P2=0x7F;//0111 1111
		Delay500ms();
	}
}

      虽然这是一种傻瓜式流水灯,但我们能实现功能就好了。就像做实物一样,不管用了什么技术,就像有一个网站,java做服务端,C++做服务端。做为一个使用者,谁会没事关注这些东西呢。

延时函数可复用

      我们不能需要用到多长时间的延时,都去创建一个函数吧,为何不把延时函数加个参数,来实现呢

#include <REGX52.H>

void Delay1ms(unsigned int xms);		//@12.000MHz

void main()
{
	while(1)
	{
		P2=0xFE;//1111 1110
		Delay1ms(1000);
		P2=0xFD;//1111 1101
		Delay1ms(1000);
		P2=0xFB;//1111 1011
		Delay1ms(100);
		P2=0xF7;//1111 0111
		Delay1ms(100);
		P2=0xEF;//1110 1111
		Delay1ms(100);
		P2=0xDF;//1101 1111
		Delay1ms(100);
		P2=0xBF;//1011 1111
		Delay1ms(100);
		P2=0x7F;//0111 1111
		Delay1ms(100);
	}
}

void Delay1ms(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

使用按键

      如果一个开关一边接到了针脚上,另一端接上1(高电平),当我们地的开关闭合时,那么针脚状态就是1,开关断开,则是0 ,我们可以去检测针脚状态来进行逻辑控制

#include <REGX52.H>

void main()
{
	while(1)
	{
		if(P3_1==0 || P3_0==0)	//如果K1按键或K2按键按下
		{
			P2_0=0;		//LED1输出0,点亮
		}
		else
		{
			P2_0=1;		//LED1输出1,熄灭
		}
	}
}
使用按键保存状态
#include <REGX52.H>

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void main()
{
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
		/*
		1\          /1
		  \        /
		   \      /
		   0\----/0
		*/
			Delay(20);		//消除下坡上坡影响
			while(P3_1==0);	//松手检测
			Delay(20);		//延时消抖
			
			P2_0=~P2_0;		//LED1取反
		}
	}
}
利用左移右移

      左移:右边补0,例:00000001<<3 -> 00000010;按位左移运算符。左操作数按位左移右操作数指定的位数(在低位补 0)。左移运算符,num << 1,相当于 num 乘以 2(每左移一位就相当于乘以一个 2)。
      按位右移运算符。左操作数按位右移右操作数指定的位数(如果该数为正数,则高位补 0 ,若为负数,则高位补 1)。右移运算符,num >> 1,相当于 num 除以 2(每右移一位相当于除以一个 2)。

#include <REGX52.H>
void Delay(unsigned int xms);

unsigned char LEDNum;

void main()
{
	P2=~0x01;				//上电默认LED1点亮
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			LEDNum++;		//LEDNum自增
			if(LEDNum>=8)	//限制LEDNum自增范围
				LEDNum=0;
			P2=~(0x01<<LEDNum);	//LED的第LEDNum位点亮
		}
		if(P3_0==0)			//如果K2按键按下
		{
			Delay(20);
			while(P3_0==0);
			Delay(20);
			if(LEDNum==0)	//LEDNum减到0后变为7
				LEDNum=7;
			else			//LEDNum未减到0,自减
				LEDNum--;
			P2=~(0x01<<LEDNum);	//LED的第LEDNum位点亮
		}
	}
}




void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}


编写自己的头文件与多文件编译

      与C语言知识相同、不做过多阐述。

  • 20
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论
软件简介 Soft Introduction这是一款全中文环境的傻瓜型BIOS、DPMI、DOS及芯片汇编语言辅助开发工具; 它包括:448个BIOS / DPMI / DOS中断功能和核心BIOS / 核心DOS中断功能,以及所有中断号和功能号的检索、7种芯片的8个芯片功能、14个功能组串和6个常用的程序框架的模板,用户只要根据自己的需要在窗口中设置选项,就可以快速、准确地自动生成相应的汇编源代码; 其中的二进制位的设置与计算(如:直接通过硬件端口传送的数据、命令)、使用哪些寄存器、大量数据的编排(如:低格时的扇区的交叉排列)等等既往需要程序员记忆、理解、计算、查资料才能完成的工作,现在都可由软件隐含自动完成。 组串将相关的中断功能组合成具有较完整功能的组串,使汇编的编程更加模块化;此外,用户还可以从BIOS、DOS中断和核心BIOS、核心DOS中断中任意选取功能,并在自由组合框中自由地组合,构建出新的、更大的模块。 程序框架模板可自动生成汇编程序的各个段、循环语句、判断语句等,用户可以象使用高级语言一样,不用考虑程序格式以及如何设置跳转标号等初级问题,把时间和精力更多地用在程序功能上,从而用汇编编出更大、更复杂、功能更强也更完善的程序来! 它是一个成功的汇编程序员所不可缺少的! 该版本和上一个版本相比较,增加了93个核心BIOS中断功能,100个核心DOS中断功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高万禄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值