单片机控制_单片机控制lora - CSDN
  • 单片机控制模块单片机控制模块单片机控制模块单片机控制模块单片机控制模块单片机控制模块
  • 单片机控制步进电机

    万次阅读 多人点赞 2019-06-06 19:07:38
    单片机控制步进电机正转 反转 加速 减速;由LCD1602实时显示步进电机的状态;F-正转,B-反转;数字越大,转速越大; 仿真原理图如下: MCU和LCD1602显示模块: ULN2803驱动和步进电机模块: C语言代码如下...

    简介:
    用单片机控制步进电机正转 反转 加速 减速;
    由LCD1602实时显示步进电机的状态;F-正转 B-反转;数字越大,转速越大;
    仿真原理图如下:
    MCU和LCD1602显示模块:
    在这里插入图片描述
    ULN2803驱动和步进电机模块:
    在这里插入图片描述
    C语言代码如下:

    /*-----------------------------
    FileName: StepperMotor.h
    Function: 函数头文件
    Author: Zhang Kaizhou
    Date: 2019-6-6 17:59:39
    ------------------------------*/
    #include <reg52.h>
    #include <string.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define Factor 5 // 转速控制常数	
    
    /*LCD1602端口设置*/
    sbit lcdrs = P1^0;
    sbit lcdrw = P1^1;
    sbit lcden = P1^2;
    
    /*步进电机驱动器端口设置*/
    sbit direcChange = P1^3; // 方向翻转
    sbit speedUp = P1^4; // 加速
    sbit slowDown = P1^5; // 减速
    
    /*主函数声明*/
    void keyScan();
    void execute();
    
    /*LCD1602显示相关函数声明*/
    void LCDInit();
    void displayInit();
    void display(uchar oper, uchar dat);
    void writeCommand(uchar command);
    void writeData(uchar dat);
    void delay(uchar xms);
    
    /*-------------------------------------------
    FileName:main.c
    Function: MCU控制步进电机
    Description:控制步进电机正转 反转 加速 减速;
    由LCD1602实时显示步进电机的状态;
    F-正转 B-反转;数字越大,转速越大;
    ---------------------------------------------
    Author: Zhang Kaizhou
    Date: 2019-6-6 17:56:41
    -------------------------------------------*/
    #include "StepperMotor.h"
    
    uchar code pulseTable0[] = {0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x04, 0x08}; // 一相励磁(同一时刻只有一个线圈通电,旋转角1.8度)
    uchar code pulseTable1[] = {0x0c, 0x06, 0x03, 0x09, 0x09, 0x03, 0x06, 0x0c}; // 二相励磁(同一时刻有两个线圈通电,旋转角1.8度)
    uchar code pulseTable2[] = {0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09,
    						    0x09, 0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08}; // 一-二相励磁场(一二相交替励磁,旋转角0.9度)
    uchar speed = 0, startPos = 0; // 默认正转
    bit oper = 0/*操作数*/, direcFlag = 0; // 初始状态为正向
    
    void main(){
    	LCDInit(); // LCD1602显示初始化
    	displayInit();
    	while(1){
    		keyScan(); // 按键扫描
    		display(0, direcFlag);
    		display(1, speed);
    		execute();
    	}
    }
    
    /*按键扫描*/
    void keyScan(){
    	if(!speedUp){ // 加速
    		delay(5);
    		if(!speedUp){
    			if(speed < 4){
    				while(!speedUp);
    				speed++;
    			}else{
    				while(!speedUp);
    				speed = 3;
    			}
    		}
    	}
    	if(!slowDown){ // 减速
    		delay(5);
    		if(!slowDown){
    			if(speed != 0){
    				speed--;
    			}else{
    				while(!slowDown);
    				speed = 0;
    			}
    		}
    	}
    	if(!direcChange){ // 方向翻转
    		delay(5);
    		if(!direcChange){
    			while(!direcChange);
    			direcFlag = ~direcFlag;
    		}
    	}
    }
    
    /*步进电机控制执行函数*/
    void execute(){
    	uchar i, j;
    	startPos = (direcFlag == 0) ? 0 : 4; // 方向控制
    	for(i = startPos; i <= (startPos + 4); i++){
    		P2 = pulseTable0[i];
    		for(j = 0; j < (speed + 1) * Factor; j++){ // 用延时来控制脉冲输出的频率,从而控制步进电机转速
    			delay(10);
    		} 
    	}
    }
    
    /*-----------------------------
    FileName:display.c
    Function: LCD1602显示函数
    Author: Zhang Kaizhou
    Date: 2019-6-6 17:58:42
    ------------------------------*/
    #include "StepperMotor.h"
    
    uchar code table0[] = {"Direction:"}; // 每行的字符数据
    uchar code table1[] = {"Speed:"};
    uchar code table2[] = {"1234"};
    uchar code table3[] = {"FB"}; // F-正向 B-反向
    
    /*初始化LCD1602的设置*/
    void LCDInit(){
    	lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
    	writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
    	writeCommand(0x0c); // 开显示,不显示光标
    	writeCommand(0x06); // 写一个字符后地址指针自动加1
    	writeCommand(0x01); // 显示清零,数据指针清零
    }
    
    /*LCD上电界面*/
    void displayInit(){
    	uchar i;
    	writeCommand(0x80); // 将数据指针定位到第一行首
    	for(i = 0; i < strlen(table0); i++){
    		writeData(table0[i]);
    		delay(5);
    	}
    	
    	writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
    	for(i = 0; i < strlen(table1); i++){
    		writeData(table1[i]);
    		delay(5);
    	}
    }
    
    /*LCD显示函数*/
    void display(uchar oper, uchar dat){
    	if(oper == 0){ // 方向显示
    		if(dat == 0){ // 正向
    			writeCommand(0x80 + strlen(table0)); // 数据指针定位到第一行空闲处
    			writeData(table3[0]);
    		}else if(dat == 1){ // 反向
    			writeCommand(0x80 + strlen(table0)); // 数据指针定位到第一行空闲处
    			writeData(table3[1]);
    		}
    	}
    	if(oper == 1){ // 速度显示
    		writeCommand(0x80 + 0x40 + strlen(table1)); // 数据指针定位到第二行空闲处
    		writeData(table2[dat]);
    	}
    }
    
    /*写指令函数*/
    void writeCommand(uchar command){
    	lcdrs = 0; // 命令选择
    	lcdrw = 0;
    	P0 = command;
    	delay(5);
    	
    	lcden = 1; // 产生一个正脉冲使能信号
    	delay(5);
    	lcden = 0;
    }
    
    /*写数据函数*/
    void writeData(uchar dat){
    	lcdrs = 1; // 数据选择
    	lcdrw = 0;
    	P0 = dat;
    	delay(5);
    	
    	lcden = 1;
    	delay(5);
    	lcden = 0;
    }
    
    /*延时函数*/
    void delay(uchar xms){
    	uint i, j;
    	for(i = xms; i > 0; i--)
    		for(j = 110; j > 0; j--);
    }
    
    展开全文
  • 第一课,了解单片机单片机控制原理和DX516 的用法,控制一个LED 灯的亮和灭本章学习内容:单片机基本原理,如何使用DX516 仿真器,如何编程点亮和灭掉一个LED 灯,如何进入KEILC51uV调试环境,如何使用单步,断点...

     第一课,了解单片机及单片机的控制原理和DX516 的用法,控制一个LED 灯的亮和灭
    本章学习内容:
    单片机基本原理,如何使用DX516 仿真器,如何编程点亮和灭掉一个LED 灯,如何进入KEILC51uV
    调试环境,如何使用单步,断点,全速,停止的调试方法
    聂小猛 2006 年6 月
    单片机现在是越来越普及了,学习单片机的热潮也一阵阵赶来,许多人因为工作需要或者个人兴趣需
    要学习单片机。可以说,掌握了单片机开发,就多了一个饭碗。
    51 单片机已经有30 多年的历史了,在中国,高校的单片机课程大多数都是51,而51 经过这么多年的
    发展,也增长了许多的系列,功能上有了许多改进,也扩展出了不少分支。而国内书店的单片机专架上,
    也大多数都是51 系列。可以预见,51 单片机在市场上只会越来越多,功能只会越来越丰富,在可以预见的
    数十年内是不可能会消失的。
    作为一个初学者,如何单片机入门?需要那些知识和设备呢?知识上,其实不需要多少东西,会简单
    的C 语言,知道51 单片机的基本结构就可以了。一般的大学毕业生都可以快速入门,自学过这2 门课程的
    高中生也够条件。
    就算你没有学过单片机课程,只掌握了C 语言的皮毛,通过本系列的教程,您也会逐渐的进入单片机
    的大门。当然在学习的过程中,您还是必须多去研读单片机书籍,了解他们的基本结构及工作方式。
    下面以51 为例来了解一下单片机是什么东西,控制原理又是什么?
    在数字电路中,电压信号只有两种情况,高电平和低电平,用数字来记录就是1 和0。单片机内部的
    CPU,寄存器,总线等等结构都是通过1 和0 两种信号来运作的,数据也是以1 或者0 来保存的。单片机
    的输入输出管脚,也就是IO 口,也是只输出或识别1 和0 两种信号,也就是高电平和低电平。当单片机输
    出一个或一组电平信号到IO 口后,外部的设备就可以读到这些信号,并进行相应操作,这就是单片机对外
    部的控制。当外部一个或一组电平信号送到单片机的IO 口时,单片机也可以读到这些信号,并进行分析操
    作,这就是单片机对外部设备信号的读取。当然实际的操作中,这些信号可能十分复杂,必须严格地按照
    规定的时间顺序(时序)输入输出。每种设备也都规定了自己的时序,只要都严格遵守,就可以控制任何
    设备,做出只要你想象得出的任何事情。
    您可能会再问,我如何让单片机去控制和分析外部设备呢?答案是程序,您可以编写相关的程序,并
    且把他们烧写到单片机内部的程序空间,单片机在上电时,就会一步一步按照您写的程序去执行指令,做
    您想做的事情。
    在51 标准芯片中,有32 个输入输出IO,分为4 组,每组8 个,分别为P0 口,P1 口,P2 口,P3 口。
    P1 口的8 条脚就用P1.0 至P1.7 表示,其余类似。51 就是用这32 个口来完成所有外部操作的。对于51 的
    内部结构,如果您已经了解,那是最好;如果不懂,也可以先放下,在完成了本教程开始的几个章节之后,
    您就会大有兴趣,自己去寻找资料阅读了。当然,如果您希望成为一个优秀的单片机开发程序员,还是必
    须熟悉单片机的内部结构及工作原理,切不可偷懒!
    在这一章,您将用程序去控制一个LED 发光管的亮和灭。你应该知道,LED 发光管在通过一定电流时
    亮,不通电就灭。为了不让LED 通过太大的电流把它烧坏,我们还要串上限流电阻。51 的IO 是弱上拉的
    方式,在输出高电平时,只能输出几十微安的电流到地,而在输出低电平时,VCC 电源可以输入几十毫安
    的电流到IO。一般LED 需要10 毫安左右电流点亮,我们就将LED 接在电源VCC 和IO 口之间,中间串
    上电阻,当IO 输出低电平时,灯就亮了,反之,灯就灭了。我们在这个程序里要控制的是P1.0。请参考一
    下我们将要使用的试验板的电路图,这个试验板是在购买dx516 仿真器是赠送的。
    图1,试验电路图


    图2:试验板外观图


    下面介绍一下仿真器和仿真环境。
    在实际的单片机学习和开发中,你可以用仿真器模拟一个CPU 芯片,让它按照您编写的程序工作,并
    且进行调试,一步步排除程序的bug,使程序正常工作。程序工作正常后,您就可以用烧写器将您编写的程
    序烧入购买来的单片机芯片中,让它自己去运行了。
    要使用仿真器,还得有一个编译调试的环境,这个环境是在计算机上运行的,我们就在计算机上编写
    和调试程序,计算机和仿真器有连接,仿真器中的各种数据和程序,都可以从计算机上观察到,并可以观
    察变量,写入变量的值,单步调试程序,在程序中设置断点调试,全速运行,停止程序运行,等等操作。
    我们使用世界上目前最先进的keilC51 编译调试环境,仿真器使用大虾电子网( http://www.daxia.com
    设计的DX516 专业版仿真器,这个仿真器功能齐全,性价比最佳,是学习开发的好工具!
    您可以在此页http://www.daxia.com/product/dx58/ 的资料下载栏目里下载到keilc51 相关的中文说明资
    料,这些资料详细地说明了如何使用C51 编程和如何使用keil uV2 环境调试,请在本章试验完成或者试验
    过程中,如果遇到不懂的地方,一定要抽时间阅读!
    您应该也可以在上面的网页中找到下载破解版本的keilc51 的办法。中国法律规定,在学习和研究工作
    中使用有版权的软件是可以的,但是,如果您开发产品时,建议您还是去购买一个正版的软件。
    下面是DX516 仿真器的使用介绍:
    1。安装
    将仿真器和试验板按图3 组装好,串口线按照正确方向插入仿真器,另一端和电脑串口连接,请尽量
    使用计算机的硬串口。
    仿真器底座左边的跳线,请放在EMB 这边,以进入仿真状态。如果放在RUN 这边,将会进入脱机运
    行状态。
    晶振选择跳线请放在IN 这边,以使用仿真器内部晶振,内部晶振更加可靠。如果放在OUT 这边,则
    会使用外部的用户板晶振。
    图3 仿真器插在试验板上


    2。电源
    因为用户板使用电流不大,可以使用usb 取电,usb 最大电流可以提供500mA,将usb 取电板插入电脑
    的usb 口中。(实际应用中,如果用户板使用电流超过100mA,我们就建议使用外部电源)
    3。启动
    在仿真器上电,或者按一下仿真器上面的按钮时,仿真器会发出“嘀-”,表示仿真器正常启动。同时
    仿真器上面的灯闪烁一次,表示进入正常仿真状态。
    4。仿真设置
    第一个设置:
    C51 用户请在您的代码的main()函数前面,加上一句:
    char code dx516[3] _at_ 0x003b;
    如果以上设置你没有做,在装载过程中,仿真器会发出“嘀嘀嘀” 的三声短声报警,这时的仿真结果将
    可能不正确。
    在我们的例程中,这句话已经加入了。这句话并不会影响程序的工作,可以一直保留。
    第二个设置:
    请在硬件仿真设置选项中,选择serial interrupt,在前面打勾。
    如果以上设置你没有做,在装载过程中,仿真器会发出“嘀-” 的一声长声报警,这时的仿真结果将可
    能不正确。
    其余设置:
    请选择use keil Monitor-51 Driver ,这样才会使用硬件仿真
    请选择load Application at start ,在启动时直接装载程序
    请选择Go till main ,装载后直接运行到main 函数
    请在硬件仿真设置选项中,选择115200bps 波特率,所有cache 都可以不选,或者只选cache code。同
    时请选择正确的串口号。
    图4 仿真设置


    好了,现在可以开始做试验了,我们打开已经建立好的工程和编写好的程序试验。顺便还会学习一下程序调
    试的技巧。至于如何建立一个新工程,请参考C51 的帮助文件,或者自己摸索一下,WWW.DAXIA.COM 的DX516
    专栏里也有“一步步教你如何第一次做…”的文章可以学习。
    请双击lessoncode01 目录下的lesson1.uv2,打开后界面如下:
    图6:程序界面


    这个界面是uV3 的,和uV2 是一样用的。
    点一下上图第三排第2 或者第3 个按钮(您的编译器按钮位置不一定在那个位置,自己找找),就可以看
    到编译结果了。上面显示是0errrs,0warnings,这是最佳的编译结果,如果有error,则无法进行下一步仿真,如果
    有warning,一定要尽量消除,确实无法消除的,也要确认不会对程序造成影响,才进行下一步的仿真。
    在编译结果中,我们还可以看到有data,xdata,code 等用了多少字节的报告,要注意您的单片机中是否有
    这么多的资源,如果不够,将来烧片运行时就可能出现问题。比如AT89C51 的程序空间是4K,xdata 如果没有外
    扩就是0 个,data 是128 个。超出这些范围,程序就不能在AT89c51 中运行。不同的芯片有不同的容量,如
    SST89E516RD 就有64K 程序,内部768 字节XDATA,还有256 个字节的data。我们的例程中肯定都考虑了这些
    了,肯定不会超出,因为DX516 仿真器是和SST89E516RD 有同样的容量的,将来自己开发时就要注意了。
    下面我们故意把第9 行的P10 写成P11,点编译,因为没有预先定义P11,所以就报告错误了,如下
    图:


    双击一下错误报告的那一行,窗口就也会跳到这一行,方便您进行修改。好了,现在请把错误改回去,再编
    译一次,出现报告正确了以后,下面开始仿真了。
    点一下第二行第5 个一个放大镜里面一个d 字母的按钮,就可以进入仿真了,仿真器要事先连接好哟。进入
    仿真后要退出仿真环境也是点这个按钮。注意,等会如果程序在正在全速运行时,仿真环境是不能直接退出的,
    得先点停止运行后,再点仿真按钮才可以退出。
    点进入仿真按钮,程序开始装载,PC 自动运行到了main()停下,并指向了main()函数的第一行。
    下面是进入了仿真环境的截图:


    再顺便把调试界面上的按钮介绍一下:
    图5:按钮说明


    进入仿真窗口后,如果出现的不是前面的源代码窗口,而是夹有反汇编代码的窗口,直接关掉这个窗口就会
    恢复到代码窗口。下次进入也会直接进入到源代码窗口。
    现在先试验单步,点单步(两个单步都可以,一般点单步跨过)。可以看到灯亮了。PC 指针也指向了下一个
    程序行。
    图:照片,灯亮
    再点一下单步,PC 又走下一步,灯灭了。
    再点一次,PC 走到挂起的程序行了,继续点仍然在这一行。这句指令其实就是使程序不断地跳到自己这一
    行,别的什么也不做。一般称作程序挂起。
    一般的实际应用中的程序是不会挂起的,一般是在main 函数里做一个大循环,程序如下:
    void main(void) // 主程序
    {
    while(1)
    {
    P11=0;//亮灯
    P10=1;//灭灯
    }
    }
    请将main 函数程序改为上面的代码,我们下一步将试验断点的操作。
    编译后结果如下:


    图:
    进入仿真后
    图:


    可以看到下面的提示窗口中显示:“connected to Monitor-51 V.DX”,后面的V.DX 就是已经连接到大虾
    仿真器的提示了。V.DX 是大虾仿真器特有的标识。
    在第15 行双击一下,可以看到程序行左边出现了一个红方块,这就是设置断点,再双击一次,断点
    就取消了。如果程序在全速运行的过程中遇到断点,就会自动停下来给你分析。注意在进入仿真后,并且
    程序是停止状态时,才可以设置或者取消断点。
    图:设置了断点


    现在点全速运行,可以看到程序在断点处停了下来,并且由于前一句指令刚刚执行了点灯,所以这时灯是
    亮着的。
    现在在第14 行设置断点,并且取消上一个断点。
    图:设置了另一个断点


    现在点全速运行,可以看到程序在断点处停了下来,并且由于刚刚执行了灭灯,灯是灭着的。
    好,现在试验全速运行和停止。
    把断点取消,再点全速运行,可以看到灯是亮着的,但是不是很亮,这是由于程序是循环的,亮灭交替进
    行,亮的时间并不是全部的时间。
    现在点停止,可以看到程序停止了,重复几次进行全速和停止,可以发现每次停止的地方不一定是同一位
    置。
    这一课就先结束了,我们学习了如何点灯及一些基本的编译和调试操作,下一课将学习如何使LED 闪烁,
    和更多的调试方法,和如何查看运行状态和设置内部寄存器的值。
    课后作业:
    改为第2 个LED 灯(P1.1)做完本章的试验。

    展开全文
  • C51单片机实验-交通灯控制

    千次阅读 2020-05-24 23:29:49
    单片机端口作输出口,控制四个方向共12个发光二极管亮灭,模拟交通灯管理。功能描述如下:初始态为四个路口的红灯全亮之后,东西路口的绿灯亮,南北路口的红灯亮,东西路口方向通车,延时一段时间后东西路口的绿灯...

    实验目的:

    1. 学习模拟交通灯控制的实现方法;
    2. 掌握Proteus硬件仿真与调试。

    任务:

    1. 根据要求编写程序,并写出原理性注释;
    2. 将检查程序运行的结果,分析一下是否正确;
    3. 完成所建工程的仿真及调试。

    实验内容

    按照电路要求在Protues中设计电路图。编程实现如下功能:
    用单片机端口作输出口,控制四个方向共12个发光二极管亮灭,模拟交通灯管理。功能描述如下:初始态为四个路口的红灯全亮之后,东西路口的绿灯亮,南北路口的红灯亮,东西路口方向通车,延时一段时间后东西路口的绿灯熄灭,黄灯开始闪烁,闪烁若干次后,东西路口红灯亮,而同时南北路口的绿灯亮,南北路口方向开始通车,延时一段时间后,南北路口的绿灯熄灭,黄灯开始闪烁,闪烁若干次后,再切换到东西路口方向,之后重复以上过程。

    交通灯控制流程图

    交通灯控制流程图

    Proteus 仿真原理图

    在这里插入图片描述

    代码

    #include <reg51.h>
    #include <absacc.h>
    typedef unsigned char uchar;
    typedef unsigned int uint;
    
    #define CON XBYTE[0x0003] //控制寄存器端口地址
    #define PA XBYTE[0x0000] //PA端口地址
    #define PB XBYTE[0x0001] //PB端口地址
    #define PC XBYTE[0x0002] //PC端口地址
    
    uchar count=0;
    uchar sum_time=0;
    //定义一个数组,用来显示计时信息
    uchar time[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10};
    
    //定时器的初始化
    void time_init(){
    	TMOD=0x10; //定时器1,模式1
    	TH1=0x3c; //定时为50ms
    	TL1=0xb0;
    	EA=1; 
    	ET1=1; 
    	TR1=0; //关闭定时
    }
    
    //中断函数
    void int_timer_1() interrupt 3{
    	TR1=0;
    	TH1=0x3c;
    	TL1=0xb0; 
    	count++; 
    	TR1=1;
    }
    
    //利用中断写的延时函数,当形参为1时,延时500ms
    void delay_500ms(uchar t){
    	time_init();
    	TR1=1; //启动定时
    	sum_time=t*10;
    	while(1){
    		if(count==sum_time){ //定时时间到
    			count=0;
    			sum_time=0;
    			TR1=0;
    			return;
    		}
    	}	
    }
    
    //将交通灯熄灭
    void clc_light(){
    	PA = 0xff;
    	PB = 0xff;
    }
    
    //8255的初始化
    void init_8255(){
    	CON=0x80;
    	clc_light();
    	PC=0x00;
    }
    
    //交通灯显示
    void traffic_lights(){
    	uchar i;
    	
    	clc_light();		
    	PA=0xf6; 
    	PB=0xdb; 
    	for(i=10;i>0;i--){
    		PC=time[i];
    		//最后3s,东西方向绿灯闪烁,南北方向红灯闪烁
    		if(i<=3){ 
    			clc_light();
    			delay_500ms(1);
    			PA=0xf6; 
    			PB=0xdb; 
    			delay_500ms(1);
    		}else{ //前7s,灯保持常亮
    			delay_500ms(2);
    		}
    	}
    	
    	//黄灯闪烁3次	
    	clc_light();
    	for(i=3;i>0;i--){
    		PC=time[i];
    		clc_light();
    		delay_500ms(1);
    		PA=0xed; 
    		PB=0xed; 
    		delay_500ms(1);
    	}
    		
    	clc_light();
    	PA=0xdb; 
    	PB=0xf6; 
    	for(i=10;i>0;i--){
    		PC=time[i];
    		//最后3s,东西方向红灯闪烁,南北方向绿灯闪烁
    		if(i<=3){
    			clc_light();
    			delay_500ms(1);
    			PA=0xdb; 
    			PB=0xf6; 
    			delay_500ms(1);
    		}else{ //前7s,灯保持常亮
    			delay_500ms(2);
    		}
    	}
    	
    	//黄灯闪烁3次
    	clc_light();
    	for(i=3;i>0;i--){
    		PC=time[i];
    		clc_light();
    		delay_500ms(1);
    		PA=0xed; 
    		PB=0xed; 
    		delay_500ms(1);
    	}		
    }
    
    void main(){
    	init_8255();
    	//初始状态,红灯全亮
    	PA=0xdb; 
    	PB=0xdb; 
    	delay_500ms(2); 
    	while(1){
    		traffic_lights();		
    	}	
    }
    
    展开全文
  • 本书详尽、系统地介绍了常用的直流电动机 、交流电动机、步进电动机、无刷直流电动机、交流永磁同步伺服电动机、开关磁阻电动机的控制原理和采用单片机进行控制的方法,并给出了单片机控制电路和软件;同时,还介绍...
  • 51单片机控制舵机

    万次阅读 多人点赞 2018-08-04 08:14:19
    舵机一般由舵盘、减速齿轮组、位置反馈电位计5k、直流电机、控制电路板等。一般情况下舵机的信号线为黄色或白色,电源分4.8V和6V,分别对应不同的转矩标准。   PWM控制方法 PWM通过占空比来控制舵机,占空比周期...

    舵机简介

    舵机一般由舵盘、减速齿轮组、位置反馈电位计5k、直流电机、控制电路板等。一般情况下舵机的信号线为黄色或白色,电源分4.8V和6V,分别对应不同的转矩标准。

     

    PWM控制方法

    PWM通过占空比来控制舵机,占空比周期T=20ms,高电平方波持续时间为0.5ms~2.5ms.对应舵机角度为:

     

     

     

    对于t = 0.5ms~2.5ms 的产生,写程序时我们可以采用全局变量。让全局变量等于5~25之间,因为舵机的一个计数周期是0.1ms,这样全局变量的5~25正好就是0.5ms~2.5ms

     

    PWM波产生思路:将信号管脚线初始化为低电平,然后写一个while循环,在循环中将该管脚置为为高电平,延时,再拉低为低电平,如此循环产生PWM波,以高电平产生时间来控制舵机转动角度。

    注意:5mv以上的控制电压的变化就会引起电机的抖动。

     

    基于单片机的控制:

     

    单片机系统实现对舵机输出转角的控制,必须先完成两个任务:

     

    1、产生    PWM周期信号,本设计产生一个20ms的周期信号;

     

    2、脉宽的调整,即单片机模拟PWM信号的输出,并调整占空比。

     

    当系统中只需要实现一个舵机的控制,采用的控制方式是改变单片机的一个定时器中断的初值,将20ms分为两次中断执行,一次短定时中断和一次长定时中断。这样既节省了硬件电路,也减少了软件开销,控制系统工作效率和控制精度都很高。

     


     具体的设计过程:例如想让舵机转向左极限的角度,它的正脉冲为2ms,则负脉冲为20ms-2ms=18ms,所以开始时在控制口发送高电平,然后设置定时器在2ms后发生中断,中断发生后,在中断程序里将控制口改为低电平,并将中断时间改为18ms,再过18ms进入下一次定时中断,再将控制口改为高电平,并将定时器初值改为2ms,等待下次中断到来,如此往复实现PWM信号输出到舵机。用修改定时器中断初值的方法巧妙形成了脉冲信号,调整时间段的宽度便可使伺服机灵活运动。

     

      为保证软件在定时中断里采集其他信号,并且使发生PWM信号的程序不影响中断程序的运行(如果这些程序所占用时间过长,有可能会发生中断程序还未结束,下次中断又到来的后果),所以需要将采集信号的函数放在长定时中断过程中执行,也就是说每经过两次中断执行一次这些程序,执行的周期还是20ms。

    如果系统中需要控制几个舵机的准确转动,可以用单片机和计数器进行脉冲计数产生PWM信号。

    脉冲计数可以利用51单片机的内部计数器来实现,但是从软件系统的稳定性和程序结构的合理性看,宜使用外部的计数器,还可以提高CPU的工作效率。

     

    
    #include <reg52.h>      
    
    #include <math.h>
    
    typedef unsigned char uchar;
    
    typedef unsigned int uint;
    
    sbit  KEY1=P3^4;					//按键1
    
    sbit  KEY2=P3^5;					//按键2
    
    sbit PWM_OUT=P2^7;				//PWM输出口
    
    uint PWM_Value;			//定义pwm值
    
    uchar order=0; 
    
    void Delay(unsigned int s);      //延时函数声明
    
    uchar flag;									//舵机按键标志
    
    
    
    
    /*延时函数*/
    void Delay(unsigned int s)
    
    {
    
    unsigned int i;
    
    for(i=0; i<s; i++);
    
    for(i=0; i<s; i++);
    
    }
    
    
    
    /*定时器初始化*/
    void Init_Timer0()        
    
    {
    
    TMOD=0x11;
    
    TH0=(65536-1500)/256;
    
    TL0=(65536-1500)%256;
    
    EA = 1;
    
    ET0 = 1;
    
    TR0 = 1;
    
    PT0=1;
    
    }               
    
    
    /*主函数*/
    void main(void)
    
    {
    
    Delay(6000);
    
    PWM_Value = 1500;					//pwm初值为1500
    
    
    
    Init_Timer0();
    
    while(1)
    
    {
    
    if((KEY1 ==0 )|(KEY2 ==0 ))							//按键1或按键2被按下
    
    {
    
    if(KEY1 ==0 )												//确认按键1被按下
    
    {
    
    flag = 1;												//标志位赋值1
    
    }
    
    if(KEY2 ==0 )									//确认按键2被按下
    
    {
    
    flag = 2;											//标志位赋值2
    
    }
    
    }
    
    else
    
    {
    
    flag = 0;								//否则标志位为0
    
    }
    
    Delay(20);								//延时20ms
    
    } 
    }
    
    
    /*****中断程序*******/
    void timer0(void) interrupt 1 
    
    {       
    
    if(flag==1)	PWM_Value += 1;							//如果标志位1时,pwm的值加1
    									
    if(flag==2)	PWM_Value -= 1;							//如果标志位为2时,pwm减1
    
    
    
    
    
    if(PWM_Value>=2500)										//如果pwm的值大于2500
    
    PWM_Value = 2500;												//则保持在2500
    
    
    
    
    
    if(PWM_Value<=500)											//如果pwm的值小于500
    
    PWM_Value=500;													//则保持在500
    
    
    
    
    
    switch(order)
    
    {
    
    	case 1:PWM_OUT=1;
    
    		   TH0=(65536-PWM_Value)>>8; 
    
    		   TL0=(uchar)(65536-PWM_Value);
    
    		   break;                          
    
    	case 2:PWM_OUT=0;
    
    		   TH0=(65536-(5000-PWM_Value))>>8;    
    
    		   TL0=(uchar)(65536-(5000-PWM_Value));
    
    		   break;                          
    
    	   
    
    	
    	case 3:
    
    		   TH0=60536>>8;   
    
    		   TL0=(uchar)60536;
    
    		   break;
    
    	case 4:
    
    		   TH0=60536>>8;   
    
    		   TL0=(uchar)60536;
    
    		   order=0;
    
    		   break;
    
    default: order=0; 
    
    		   break;
    
    }
    
              order++;
    
    }

     

    展开全文
  • 单片机控制步进电机-电路连接

    千次阅读 多人点赞 2019-02-22 21:26:14
    单片机控制步进电机-线路连接 说明:如何利用单片机去控制步进电机?本案例讲解的内容是硬件连接部分,采用常用的电子器件去实现单片机控制步进电机的功能。后续会分别讲解单片机程序,S曲线生成方法,上位机等...
  • 51单片机控制LCD1602模块

    万次阅读 多人点赞 2018-04-07 23:52:56
    51单片机控制LCD1602模块视频播放:LCD1602视频(1)LCD1602概述先来看看LCD1602什么意思?Liquid Crystal Display(LCD)表示液晶显示,1602 表示一行可以显示16个字符,一共有两行。现在我们来看看如何使用简单的IO...
  • 单片机控制步进电机-AVR详细程序

    千次阅读 2019-02-22 21:24:48
    单片机控制步进电机-单片机程序(avr) 硬件线路连接图见上一篇文章 软件: ICCV7 FOR AVR-写程序 Progisp-烧程序 速度S曲线生成器(后续后单独讲解)-生成S曲线数组代码 硬件: Atmega16 ASP下载线 杜邦...
  • 51单片机控制TB6600驱动器驱动42步进电机

    千次阅读 多人点赞 2020-08-15 10:45:44
    51单片机控制TB6600驱动器驱动42步进电机功能实现目标硬件简介硬件连接程序代码功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个...
  • 单片机控制跑马灯

    万次阅读 2015-11-19 16:23:51
    二、单片机控制LED灯的常用电路接法 弄清楚跑马灯的显示状态后可以开始进行设计了, 在日常的跑马灯设计电路中LED灯一般接为这两种形式,共电源或共地,也就是通常说的灌电流式和拉电流式 三、电路分析与编程 ...
  • 单片机控制ws2812b

    万次阅读 2016-08-20 16:46:57
    单片机程序转: http://www.ndiy.cn/thread-36302-1-1.html 代码如下: /********************************************************/ .../*程序功能:用51单片机控制ws2812 RGB输出,显示全
  • 单片机控制继电器 使LED灯交替闪烁

    万次阅读 2016-11-02 01:36:00
    今天看到了继电器,想用89C51单片机控制它,使其能控制更丰富的电路,以完成一些复杂的功能。 首先用单片机的P2^0直接加到继电器上,发现没有反应,于是查了相关资料。发现单片机引脚输出的电流太小,不足以驱动继电...
  • 单片机控制LED灯要怎样编写?

    千次阅读 2008-04-17 17:16:00
    单片机控制LED灯要怎样编写?正文: 用单片机控制LED灯要怎样编写? 我想要一个程序是这样:控制环形灯从最上面的一盏灯开始亮,然后熄了,然后顺着第二盏灯亮了,然后熄了,然后第三盏亮了,又熄了……这样一直到...
  • 单片机控制三极管

    千次阅读 2017-05-12 22:57:22
    单片机控制三极管 如果你高中的物理知识还没有全部还给体育老师,那么你应该知道,三极管可以放大电流。 看下面这个电路图,如果单片机输出低电平0V,没有电流流过,自然也不能放大,LED不发光,我们可以定义一下...
  • 单片机控制继电器实验

    千次阅读 2012-11-11 00:09:06
    单片机控制继电器实验  在各种自动控制设备中,都存在一个低压的自动控制电路与高压电气电路的互相连接问题,一方面要使低压的电子电路的控制信号能够控制高压电气电路的执行元件,如电动机、电磁铁、电灯等;另...
  • 单片机控制数码管显示不同数字

    千次阅读 2019-11-28 20:17:52
    数码管显示的数字是通过单片机控制的,本篇文章为你讲述其中的原理。 文章涉及到的电路图和程序源码大家可以关注我的同名公众号,回复:“下载-单片机自学教程1”即可获取。仿真软件的安装以及破解教程,关注后会...
  • 单片机控制TFT液晶屏显示数字

    千次阅读 2017-09-20 21:52:20
    单片机控制TFT液晶屏显示数字,此工程的硬件部分如下  单片机部分 液晶电路 接下来就是软件部分程序的编写,我们先来看main函数,main函数如下 main函数里做了3件事,第一件就是对TFT液晶屏的初始...
  • 我想做一个开关 用51单片机控制家庭电源 应该选择什么型号的继电器 还有可以用1个uln2803驱动8个继电器吗 谢谢啦!!!
  • 单片机控制步进电机的方法很简单,可以用IO口输出脉冲控制线圈电流驱动电机旋转,可分为四相四拍,四相八拍。四相电机,有四相四拍运行方式AB-BC-CD-DA-AB,四相八拍运行方式即 A-AB-B-BC-C-CD-D-DA-A。前面文档给...
1 2 3 4 5 ... 20
收藏数 65,476
精华内容 26,190
关键字:

单片机控制