开发者社区> feipeng8848> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

51单片机入门程序

简介: 注:昨天有同学指正说流水灯会影响脉冲输出,造成4s时间的延误。这里说明下,程序设计的初衷是让每个任务独立运行,意思就是当流水灯任务执行的时候脉冲输出任务就被挂起,不过实际上流水灯工作的时候脉冲输出引脚的确会一直维持一个电平,没考虑周详,多谢这位同学提出。最后附上了新的解决方案,中断方式,欢迎同道指正。 需求:通过按下不同的按键让STC89C52RC控制电机以不同的转速运行或者控制LED实
+关注继续查看

注:昨天有同学指正说流水灯会影响脉冲输出,造成4s时间的延误。这里说明下,程序设计的初衷是让每个任务独立运行,意思就是当流水灯任务执行的时候脉冲输出任务就被挂起,不过实际上流水灯工作的时候脉冲输出引脚的确会一直维持一个电平,没考虑周详,多谢这位同学提出。最后附上了新的解决方案,中断方式,欢迎同道指正。

需求:通过按下不同的按键让STC89C52RC控制电机以不同的转速运行或者控制LED实现流水灯。

需求分析:

按下按键1流水灯开始工作,按下按键2电机以低转速运行,按下按键3电机以中转速运行,按下按键4电机以高转速运行。

总结下,程序可分为如下三块:

(1)扫描按键

(2)流水灯

(3)发出三种不同速度的脉冲信号(用以控制电机不同转速)

解决方案:

程序分为两层,应用层和底层,应用层实现各个任务,底层实现一些基本操作(例如延时程序)

(1)应用层函数:单片机运行三个任务,分别是:扫描键盘、控制LED、控制电机。

(2)底层函数:延时函数、流水灯函数、脉冲输出函数

代码实现:

#include<reg51.h>

sbit P24=P2^4;//脉冲输出口

sbit P20=P2^0;//按键
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;

unsigned char flag=0x00;//按键标量(看懂这个变量是啥意思,整个程序的思路就能全部看懂了!!!)

//应用层函数(任务)
void LED_Mission(unsigned char flag);//LED任务
void Motor_Mission(unsigned char flag);//电机任务
void Key_Mission();//扫描键盘任务

//底层函数
void PWM(unsigned char time);
void LED();
void Delay(int ms);


void main()//主函数
{
	while(1)
	{
		Key_Mission();
		LED_Mission(flag);
		Motor_Mission(flag);
	}
}


/*####################################
Key_Mission,扫描键盘任务
#####################################*/
void Key_Mission()//根据键盘更改按键标量
{
    if(P20==0)
	{
		Delay(3);//去抖动
	    if(P20==0)
		flag=0x00;
	}
	if(P21==0)
	{
		Delay(3);
	    if(P21==0)
		flag=0x01;
	}
	if(P22==0)
	{
		Delay(3);
	    if(P22==0)
		flag=0x02;
	}
	if(P23==0)
	{
		Delay(3);
	    if(P23==0)
		flag=0x03;
	}
	
}
/*####################################
LED_Mission,控制LED流水灯任务
#####################################*/
void LED_Mission(unsigned char flag)
{
    if(flag!=0x00)
    return;
    LED();
}
/*####################################
Motor_Mission,电机控制任务
#####################################*/
void Motor_Mission(unsigned char flag)
{
    switch(flag)
    {
        case 0x01:
        PWM(1);
        break;
        case 0x02:
        PWM(5);
        break;
        case 0x03:
        PWM(9);
        break;
    }
}

/*####################################
PWM,脉冲输出子函数,根据参数发送不同速度的脉冲
#####################################*/
void PWM(unsigned char num)//输出脉冲信号,根据参数不同脉冲速度不一样
{
    P24=0;
    Delay(num*50);//倍率待定,暂定50,根据实际情况更改
    P24=1;
    Delay(num*50);//倍率待定,暂定50,根据实际情况更改
}
/*####################################
LED,流水灯程序
#####################################*/
void LED()
{
    //流水灯程序
	P1=0xFE;
	Delay(500);
	P1=0xFD;
	Delay(500);
	P1=0xFB;
	Delay(500);
	P1=0xF7;
	Delay(500);
	P1=0xEF;
	Delay(500);
	P1=0xDF;
	Delay(500);
	P1=0xBF;
	Delay(500);
	P1=0x7F;
	Delay(500);
	P1=0xFF;
	Delay(500);
}
/*####################################
Delay,延时程序
#####################################*/
void Delay(int ms)
{
    //延时程序
	unsigned char a,b,c,i;
	for(i=0;i<ms;i++)
	{
		for(a=0;a<1;a++)
		for(b=0;b<3;b++)
		for(c=0;c<219;c++);
	}
}


keil下编译无错无警告:


注:只是编译无错,没有烧录到单片机上实验。具体实现可能需要更改相应参数。

*************************************************************************************************

*************************************************************************************************

******************************************分割线*************************************************

*************************************************************************************************

*************************************************************************************************

中断方式

以上采用了查询方式,优点是思路简单,缺点是实时性能太差。

那么为了解决实时性差这个问题,这里采用中断方式

需求:通过按下不同的按键让STC89C52RC控制电机以不同的转速运行或者控制LED实现流水灯。

需求分析:

按下按键1,流水灯慢速工作,电机慢速工作。按下按键2,流水灯快速工作,电机慢快速工作。

总结下,程序大体思路如下:

按键1触发外部中断0,按键2触发外部中断1。定时器0用作脉冲输出。


外部中断0触发之后设置流水灯的延时时间的数值大一些(延时时间就会长一点),同时设置定时器0的预装值小一些(这样脉冲输出的频率会慢一些)。


外部中断1触发之后设置流水灯的延时时间的数值小一些(延时时间就会短一点),同时设置定时器0的预装值大一些(这样脉冲输出的频率会快一些)。

解决方案:

任务1:LED流水灯

任务2:三个中断处理程序

三个中断处理程序分别是,外部中断0、外部中断1、定时器0

代码实现:

#include<reg51.h>

sbit P24=P2^4;//脉冲输出口
unsigned int InitTL0=0x1111;//默认数值比较小,脉冲周期较长
unsigned int InitTH0=0x1111;

sbit P25=P2^5;//接IN1
sbit P26=P2^6;//接IN2

unsigned int DelayTime=0xC8;//默认200ms,流水灯速度较慢


//底层与各种初始化函数
void Delay(int ms);
void InitInt();//初始化外部中断0和外部中断1
void InitT0();//初始化定时器0


//流水灯任务
void LED_Mission();//led流水


//中断任务
void exint0() interrupt 0           //外部中断0
{
	InitTL0=0xFFFF;
	InitTH0=0xFFFF;
	DelayTime=0x30;//48ms
}
void exint1() interrupt 2           //外部中断1
{
	InitTL0=0x1111;
	InitTH0=0x1111;
	DelayTime=0xC8;//200ms
}
void tm0_isr() interrupt 1 using 1 //定时器0中断
{
	P24=~P24;
	TL0=InitTL0;
  TH0=InitTH0;	
}






//主函数
void main()
{
	P24=0;
	P25=0;
	P26=1;
	InitInt();
	InitT0();
	while(1)
	{
		LED_Mission();
	}
}




/*####################################
LED,流水灯程序
#####################################*/
void LED_Mission()
{
    //流水灯程序
	P1=0xFE;
	Delay(DelayTime);
	P1=0xFD;
	Delay(DelayTime);
	P1=0xFB;
	Delay(DelayTime);
	P1=0xF7;
	Delay(DelayTime);
	P1=0xEF;
	Delay(DelayTime);
	P1=0xDF;
	Delay(DelayTime);
	P1=0xBF;
	Delay(DelayTime);
	P1=0x7F;
	Delay(DelayTime);
	P1=0xFF;
	Delay(DelayTime);
}


/*####################################
Delay,延时程序
#####################################*/
void Delay(int ms)
{
    //延时程序
	unsigned char a,b,c,i;
	for(i=0;i<ms;i++)
	{
		for(a=0;a<1;a++)
		for(b=0;b<3;b++)
		for(c=0;c<219;c++);
	}
}



/*####################################
InitInt,初始化外部中断
#####################################*/
void InitInt()
{
	  IT0 = 1;                        
    EX0 = 1; 
    IT1 = 1;                      
    EX1 = 1;                        
    EA = 1;      
}



/*####################################
InitT0,初始化定时器0
#####################################*/
void InitT0()
{
		TMOD=0x01;
		TR0 = 1;                      
		ET0 = 1;
}





第一段代码,只是编译无错,没烧写到单片机上具体实验。第二段代码,烧写到单片机上仅测试了流水灯正常工作,可调速,未测试脉冲输出。欢迎指正。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
ThreadLocal能解决线程安全问题?胡扯!本文教你正确的使用姿势【享学Java】(中)
ThreadLocal能解决线程安全问题?胡扯!本文教你正确的使用姿势【享学Java】(中)
89 0
LCD1602单片机(STC51/STM32)驱动程序详解
LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。
417 0
ASP.NET MVC4 音乐商店,Entity Framework 4.1 表名被自动转换成复数问题解决
 做ASP.NET MVC3 Music Store示例时,   EntityFramework4.1 下表名被自动转换成复数问题: 解决方案:    using System; using System.
814 0
一个经典的控制Led的单片机程序
这本来是我在大三时期做的一个题目,属于课外习题。题目是这样的,在单片机课程中,有一个实验是控制数码管显示一个时钟。程序逻辑非常简单,可以用如下的伪码表示。 while(true) {     累加ms时间并进位;     if(ScanKeys(&code))         ProcessKey(code);         //处理按键      Display() ;                            //刷新数码管显示 } 上面的逻辑是凭借记忆,并且实际上是使用8051汇编语言编写,控制6个Led7段式数码管。
878 0
+关注
71
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载