飞道的博客

《单片机傻瓜篇》

224人阅读  评论(0)

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

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

单片机针脚

C51系列单片机有4*8=32个针脚。p0,p1,p2,p3三个寄存器,每个寄存器大小为8位,干什么用的呢?这些针脚只有两种状态即0(低电平)与1(高电平)。我们可以通过写程序,通过编译器生成CPU的一条条指令,烧录到里面去。我们通过对针脚的高低电平进行逻辑判断,再通过一系列状态对针脚状态做出改变。
举一个例子,比如查看某个针脚状态,读到了1,可以假想(另一个针脚上连着电机),我们改变针脚状态,让电机转起来。

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语言知识相同、不做过多阐述。


转载:https://blog.csdn.net/qq_45812941/article/details/116900921
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场