51单片机嵌入式开发:17、STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息

51单片机嵌入式开发


STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息

  • 51单片机嵌入式开发
  • STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息
  • 1 概述
  • 2 硬件电路
    • 2.1 遥控器
    • 2.2 红外接收器电路
    • 2.3 STC89C52单片机电路
    • 2.4 数码管显示电路
    • 2.5 串口打印电路
    • 2.6 步进电机电路
  • 3 工程代码实现
    • 3.1 红外接收程序
    • 3.2 定时器程序
    • 3.3 数码管显示程序
    • 3.4 外部中断程序
    • 3.5 串口打印程序
    • 3.6 步进电机程序
    • 3.7 演示效果
  • 4 设计总结


STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息

在这里插入图片描述

1 概述

基于STC89C52单片机控制步进电机并通过遥控器控制转速和转向,同时使用printf打印信息是一个涉及到多个方面的复杂项目。下面是一个简单的设计思路:

(1) 在C51单片机上,连接HX1838红外解码器、数码管和LED。将HX1838的信号引脚连接到C51单片机的外部中断引脚(例如INT0),数码管的CLK引脚连接到C51单片机的某个IO口引脚,数码管的DIO引脚连接到C51单片机的另一个IO口引脚,LED连接到C51单片机的某个IO口引脚。
(2) 在C51程序中,定义并初始化所需的IO口和外部中断。
(3) 编写中断服务函数以处理红外解码。当外部中断触发时,读取HX1838接收到的红外信号并解码。
(4) 根据解码结果,使用适当的算法将其转换为数码管的显示数据。
(5) 将数码管的显示数据发送到数码管的CLK和DIO引脚,以控制数码管显示解码结果。
(6) 根据解码结果的状态,设置LED引脚状态以控制LED的显示。
(7) 通过循环等待的方式持续接收和处理红外信号,并更新数码管和LED的显示。
(8) 通过循环等待的方式,持续接收和处理红外信号,并更新数码管和LED的显示。
(9) 根据不同的指令信息控制步进电机的转速和转向。

2 硬件电路

2.1 遥控器

外部遥控器的编码见下图,我们用0x44、0x40、0x07、0x15这四个按键控制步进电机的转速和转向。
在这里插入图片描述

2.2 红外接收器电路

红外接收器电路见下图:

在这里插入图片描述

2.3 STC89C52单片机电路

单片机接口电路见下图:P10~P13接步进电机。

在这里插入图片描述

2.4 数码管显示电路

数码管显示电路接口电路见下图,在数码管0和1进行显示16进制的红外线接收码:

在这里插入图片描述

2.5 串口打印电路

串口打印电路接口电路见下图(其实用下载电路也能实现串口的通讯):

在这里插入图片描述

2.6 步进电机电路

步进电机电路如下:
将P1端口跳线接到左边位置处,ABCD对应位置,将步进电机的排母接到右边位置,红色引线为VCC。
在这里插入图片描述

3 工程代码实现

工程、主程序及includes.h如下:

//main.c文件

#include "includes.h"///******************************************************************/
///*                    微秒延时函数  //10us                         */
///******************************************************************/
//void delay_us(unsigned int us)//delay us
//{
//	while(us--)
//	{
//	}
//}///******************************************************************/
///*                    微秒延时函数                                */
///******************************************************************/
//void delay_ms(unsigned int Ms)//delay us
//{
//	while(Ms--)
//	{
//		delay_us(100);
//	}
//}/*------------------------------------------------延时子程序
------------------------------------------------*/
void delay(unsigned int cnt) 
{while(--cnt);
}/*------------------------------------------------主函数
------------------------------------------------*/
void main (void)
{bit flag = 0;sys_timer_init();sys_exit_init();sys_uart_init();//	sys_ledtube_on2();
//	
//	sys_ledtube_on1();delay(10);//首先定义处于什么状态,//tx1838_type = 1;printf("Hello world~~");byj48_value = 300;while (1){
//		sys_tx1838_test();if(tx1838_flag){tx1838_flag = 0;hx1838_transform(tx1838_value);}sys_28byj48_func(byj48_type,byj48_value);if(flag){flag = 0;sys_keynum_ledon(tx1838_value>>4,0);}else{flag = 1;sys_keynum_ledon(tx1838_value&0xF,1);}}
}

//includes.h文件

#ifndef __INCLUDES_H__
#define __INCLUDES_H__//#include<reg52.h> #include<intrins.h> //汇编指令_nop_
#include<stdio.h> 	//标准输入输出//_nop_(); 产生一条NOP指令
//作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。
//NOP指令为单周期指令,可由晶振频率算出延时时间。//8051 为每个机器周期 12 时钟
//对于12M晶振,延时1uS。
//11.0592M晶振,延时1.0851uS。//对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "STC89C5xRC_RDP.h"//应用层头文件
//#include "c51_gpio.h"
#include "c51_ledtube.h"
//#include "c51_key.h"
#include "c51_timer.h"
#include "c51_exit.h"
//#include "c51_lcd1602.h"
//#include "c51_iic.h"
#include "c51_tx1838.h"
#include "c51_uart.h"
#include "c51_28byj48.h"extern void delay(unsigned int cnt);
//extern void delay_us(unsigned int us);//delay us;
//extern void delay_ms(unsigned int Ms);//delay Ms;#endif

3.1 红外接收程序

实现红外nec解码和根据码位不同,在printf打印不同的字符串。

//c51_tx1838.c文件

#include "includes.h"unsigned char tx1838_cnt = 0;
unsigned char tx1838_type = 0;
unsigned char tx1838_flag = 0;
unsigned char tx1838_repeat_flag = 0;unsigned char tx1838_value = 0;
unsigned char tx1838_data[4] = {0};
unsigned int  tx1838_time = 0;//void sys_tx1838_test(void)
//{
//	unsigned int time = 0;
//	if(!NEC)
//	{
//		while(!NEC);		//等待低电平结束
//		TH0 = 0;
//		TL0 = 0;
//		delay_us(1);
//		if(tx1838_type==4)
//		{
//			tx1838_type =1;
//		}
//		else
//		{
//			while(NEC)			//等待数据位计时
//			{
//				if(TH0>30)
//				{
//					tx1838_type =1;
//					break;
//				}
//			}
//		}
//		time =(TH0<<8)+TL0; //取得脉冲宽度
//	
//		switch(tx1838_type)
//		{
//			case 1:
//			{
//				if(time>3000 && time<7000) //接收到数据
//				{
//					tx1838_type = 2;
//					
//					tx1838_cnt = 0;		//接收位数量清0
//					tx1838_data[0] = 0;
//					tx1838_data[1] = 0;
//					tx1838_data[2] = 0;
//					tx1838_data[3] = 0;
//				}
//				else if(time>2000 && time<3000)//接收到重复码
//				{
//					tx1838_type = 3;
//				}
//				else
//				{
//					tx1838_type = 1;
//				}
//				break;
//			}
//			case 2:
//			{
//				tx1838_cnt ++ ;
//				if(time>168 && time<800) //接收到数据位为0的时间长度
//				{//				}
//				else 
//				{
//					if(time>1100 && time<1800) //接收到数据位为1的时间长度
//					{
//						if(tx1838_cnt<=8)
//						{
//							tx1838_data[0] |= (1<<(tx1838_cnt-1));
//						}
//						else if(tx1838_cnt<=16)
//						{
//							tx1838_data[1] |= (1<<(tx1838_cnt-9));
//						}
//						else if(tx1838_cnt<=24)
//						{
//							tx1838_data[2] |= (1<<(tx1838_cnt-17));
//						}
//						else if(tx1838_cnt<=32)
//						{
//							tx1838_data[3] |= (1<<(tx1838_cnt-25));
//						}
//						else
//						{
//							tx1838_type = 1;
//							
//							tx1838_cnt = 0;		//接收位数量清0
//							tx1838_data[0] = 0;
//							tx1838_data[1] = 0;
//							tx1838_data[2] = 0;
//							tx1838_data[3] = 0;
//						}
//					}
//					else //重新解码 //接收到引导码或者结束码,或者接收到的是重复码,本章节不进行演示
//					{
//						tx1838_type = 1;
//						
//						tx1838_cnt = 0;		//接收位数量清0
//						tx1838_data[0] = 0;
//						tx1838_data[1] = 0;
//						tx1838_data[2] = 0;
//						tx1838_data[3] = 0;
//					}
//				}
//				
//				if(tx1838_cnt>=32)
//				{
//					tx1838_type = 4;
//					
//					switch(tx1838_data[3])//判断数码值
//					{
//						case 255:sys_keynum_ledon(0);break;//0 显示相应的按键值
//						case 254:sys_keynum_ledon(1);break;//1
//						case 253:sys_keynum_ledon(2);break;//2
//						case 252:sys_keynum_ledon(3);break;//3
//						case 251:sys_keynum_ledon(4);break;//4
//						case 250:sys_keynum_ledon(5);break;//5
//						case 249:sys_keynum_ledon(6);break;//6
//						case 248:sys_keynum_ledon(7);break;//7
//						case 247:sys_keynum_ledon(8);break;//8
//						case 246:sys_keynum_ledon(9);break;//9 显示相应的按键值//					}
//				}
//				break;
//			}
//			case 3: //重复码
//			{
//				tx1838_type = 1;
//				sys_keynum_ledon(11);
//				break;
//			}
//			case 4: //结束码
//			{
//				tx1838_type = 1;
//				
//				tx1838_cnt = 0;		//接收位数量清0
//				
//				break;
//			}
//			case 5:
//			{
//				break;
//			}
//			default:
//				tx1838_type = 1;
//				break;
//		}
//			
//	}
//}void sys_nec_test(void)
{if(tx1838_type==0)				//状态0,空闲状态{timer0_set(0);				//定时计数器清0timer0_run(1);				//定时器启动tx1838_type=1;				//置状态为1}else if(tx1838_type==1)			//状态1,等待Start信号或Repeat信号{tx1838_time=timer0_get();	//获取上一次中断到此次中断的时间timer0_set(0);				//定时计数器清0//如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)if(tx1838_time>12442-500 && tx1838_time<12442+500){tx1838_type=2;			//置状态为2}//如果计时为11.25ms,则接收到了repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)else if(tx1838_time>10368-500 && tx1838_time<10368+500){tx1838_repeat_flag=1;	//置收到连发帧标志位为1timer0_run(0);		//定时器停止tx1838_type=0;		//置状态为0}else					//接收出错{tx1838_type=1;			//置状态为1}}else if(tx1838_type==2)		//状态2,接收数据{tx1838_time=timer0_get();	//获取上一次中断到此次中断的时间timer0_set(0);	//定时计数器清0//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)if(tx1838_time>1032-500 && tx1838_time<1032+500){tx1838_data[tx1838_cnt/8]&=~(0x01<<(tx1838_cnt%8));	//数据对应位清0tx1838_cnt++;			//数据位置指针自增}//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)else if(tx1838_time>2074-500 && tx1838_time<2074+500){tx1838_data[tx1838_cnt/8]|=(0x01<<(tx1838_cnt%8));	//数据对应位置1tx1838_cnt++;			//数据位置指针自增}else					//接收出错{tx1838_cnt=0;			//数据位置指针清0tx1838_type=1;			//置状态为1}if(tx1838_cnt>=32)		//如果接收到了32位数据{tx1838_cnt=0;			//数据位置指针清0if((tx1838_data[0]==~tx1838_data[1]) && (tx1838_data[2]==~tx1838_data[3]))	//数据验证{//地址		:tx1838_data[0]//地址反码	:tx1838_data[1]//数据		:tx1838_data[2]//数据反码	:tx1838_data[3]tx1838_value = tx1838_data[2];//P1 = tx1838_value;tx1838_flag=1;	//红外遥控获取收到数据帧标志位}timer0_run(0);		//定时器停止tx1838_type=0;			//置状态为0}}
}void hx1838_transform(unsigned char cmd)
{/*#define TX1838_CH0			0x45
#define TX1838_CH1			0x46
#define TX1838_CH2			0x47
#define TX1838_VOL1			0x44
#define TX1838_VOL2			0x40
#define TX1838_VOL3			0x43
#define TX1838_EQ1			0x07
#define TX1838_EQ2			0x15
#define TX1838_EQ3			0x09
#define TX1838_0			0x16
#define TX1838_100			0x19
#define TX1838_200			0x0D
#define TX1838_1			0x0C
#define TX1838_2			0x18
#define TX1838_3			0x5E
#define TX1838_4			0x08
#define TX1838_5			0x1C
#define TX1838_6			0x5A
#define TX1838_7			0x42
#define TX1838_8			0x52
#define TX1838_9			0x4A*/switch(cmd){case TX1838_CH0://printf("Receice cmd : TX1838 receice is TX1838_CH0 !\r\n");break;case TX1838_CH1://printf("Receice cmd : TX1838 receice is TX1838_CH1 !\r\n");break;case TX1838_CH2://printf("Receice cmd : TX1838 receice is TX1838_CH2 !\r\n");break;case TX1838_VOL1:byj48_type = 0;printf("Receice cmd : TX1838 receice is	正转	!\r\n");break;case TX1838_VOL2:byj48_type = 1;printf("Receice cmd : TX1838 receice is 反转 !\r\n");break;case TX1838_VOL3:printf("Receice cmd : TX1838 receice is 加速 !\r\n");break;case TX1838_EQ1:if(byj48_value<300){byj48_value = 300;}byj48_value -= 10;printf("Receice cmd : TX1838 receice is 加速 !\r\n");break;case TX1838_EQ2:if(byj48_value>1000){byj48_value = 1000;}byj48_value += 10;printf("Receice cmd : TX1838 receice is 减速 !\r\n");break;
//		case TX1838_EQ3:
//			printf("Receice cmd : TX1838 receice is TX1838_EQ3 !\r\n");
//			break;
//		case TX1838_0:
//			printf("Receice cmd : TX1838 receice is TX1838_0 !\r\n");
//			break;
//		case TX1838_100:
//			printf("Receice cmd : TX1838 receice is TX1838_100 !\r\n");
//			break;
//		case TX1838_200:
//			printf("Receice cmd : TX1838 receice is TX1838_200 !\r\n");
//			break;
//		case TX1838_1:
//			printf("Receice cmd : TX1838 receice is TX1838_1 !\r\n");
//			break;
//		case TX1838_2:
//			printf("Receice cmd : TX1838 receice is TX1838_2 !\r\n");
//			break;
//		case TX1838_3:
//			printf("Receice cmd : TX1838 receice is TX1838_3 !\r\n");
//			break;
//		case TX1838_4:
//			printf("Receice cmd : TX1838 receice is TX1838_4 !\r\n");
//			break;
//		case TX1838_5:
//			printf("Receice cmd : TX1838 receice is TX1838_5 !\r\n");
//			break;
//		case TX1838_6:
//			printf("Receice cmd : TX1838 receice is TX1838_6 !\r\n");
//			break;
//		case TX1838_7:
//			printf("Receice cmd : TX1838 receice is TX1838_7 !\r\n");
//			break;
//		case TX1838_8:
//			printf("Receice cmd : TX1838 receice is TX1838_8 !\r\n");
//			break;
//		case TX1838_9:
//			printf("Receice cmd : TX1838 receice is TX1838_9 !\r\n");
//			break;default:printf("Receice cmd : TX1838 receice err!\r\n");break;}
}

//c51_tx1838.h文件

#ifndef __C51_TX1838_H__
#define __C51_TX1838_H__#define  NEC 	P32 //红外线接收头  #define TX1838_CH0			0x45
#define TX1838_CH1			0x46
#define TX1838_CH2			0x47
#define TX1838_VOL1			0x44
#define TX1838_VOL2			0x40
#define TX1838_VOL3			0x43
#define TX1838_EQ1			0x07
#define TX1838_EQ2			0x15
#define TX1838_EQ3			0x09
#define TX1838_0			0x16
#define TX1838_100			0x19
#define TX1838_200			0x0D
#define TX1838_1			0x0C
#define TX1838_2			0x18
#define TX1838_3			0x5E
#define TX1838_4			0x08
#define TX1838_5			0x1C
#define TX1838_6			0x5A
#define TX1838_7			0x42
#define TX1838_8			0x52
#define TX1838_9			0x4Aextern unsigned char tx1838_cnt;
extern unsigned char tx1838_type;
extern unsigned char tx1838_flag;
extern unsigned char tx1838_repeat_flag;
extern unsigned char tx1838_value;
extern unsigned char tx1838_data[4];
extern unsigned int tx1838_time;//extern void sys_tx1838_test(void);
extern void sys_nec_test(void);
extern void hx1838_transform(unsigned char cmd);#endif

3.2 定时器程序

//c51_timer.c文件

#include "includes.h"void sys_timer_init(void)
{sys_timer0_init();sys_timer1_init();sys_timer2_init();sys_wdog_init();clr_wdg();
}/*------------------------------------------------定时器初始化子程序
------------------------------------------------*/
void sys_timer0_init(void)
{TMOD &= 0xF0;TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     TH0=0x00;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出TL0=0x00;//EA=1;            //总中断打开 等最后一个中断打开//ET0=1;           //定时器中断打开TF0=0;           //定时器标志清零TR0=0;           //定时器开关打开
}/*------------------------------------------------定时器初始化子程序
------------------------------------------------*/
void sys_timer1_init(void)
{TMOD |= 0x20;	  //使用模式2,	     TH1=0x05;	      //给定初值,这里使用定时器最大值从5开始计数一直到255溢出TL1=0x00;//EA=1;            //总中断打开//ET1=1;           //定时器中断打开//TR1=1;           //定时器开关打开
}/*------------------------------------------------定时器初始化子程序
------------------------------------------------*/
void sys_timer2_init(void)
{RCAP2H = 0/256;//RCAP2L = 0/256;//ET2=1;                     //打开定时器中断//EA=1;                      //打开总中断//TR2=1;                     //打开定时器开关
}/*** @brief  定时器0设置计数器值* @param  Value,要设置的计数器值,范围:0~65535* @retval 无*/
void timer0_set(unsigned int Value)
{TH0=Value/256;TL0=Value%256;
}/*** @brief  定时器0获取计数器值* @param  无* @retval 计数器值,范围:0~65535*/
unsigned int timer0_get(void)
{return ((TH0<<8)|TL0);
}/*** @brief  定时器0启动停止控制* @param  Flag 启动停止标志,1为启动,0为停止* @retval 无*/
void timer0_run(unsigned char Flag)
{TR0=Flag;
}void sys_wdog_init(void)
{ //WDT_CONTR = 0x35;
}void clr_wdg(void)
{//WDT_CONTR = 0x35;
}/*------------------------------------------------定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{TH0=0x00;		  //重新赋值TL0=0x00;//sys_led_test1(); //流水灯操作
}/*------------------------------------------------定时器中断子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3
{//sys_led_test1(); //流水灯操作}	/*------------------------------------------------定时器中断子程序
------------------------------------------------*/
void Timer2_isr(void) interrupt 5//定时器2中断
{TF2=0;//sys_led_test1(); //流水灯操作
}

//c51_timer.h文件

#ifndef __C51_TIMER_H__
#define __C51_TIMER_H__extern void timer0_set(unsigned int Value);
extern unsigned int timer0_get(void);
extern void timer0_run(unsigned char Flag);extern void sys_timer_init(void);
extern void sys_timer0_init(void);
extern void Timer0_isr(void);
extern void sys_timer1_init(void);
extern void Timer1_isr(void);
extern void sys_timer2_init(void);
extern void Timer2_isr(void);extern void sys_wdog_init(void);
extern void clr_wdg(void);#endif

3.3 数码管显示程序

实现数码管显示遥控器的发送码。

//c51_ledtube.c文件

#include "includes.h"// 显示段码值01234567,可对应原理图查看显示不同图形对应的引脚高点电平配置状态
unsigned char const EL[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,\0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F///********************************************************
//函数名称:sys_ledtube_on1
//函数功能:点亮一个数码管全为亮起来
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//void sys_ledtube_on1(void)
//{
//	//根据原理图,将P0口全部输出高电平,P2选择0号数码管
//	P0=0xFF;//取显示数据,段码
//	P2=0;  	//取位码
//}///********************************************************
//函数名称:sys_ledtube_on2
//函数功能:显示一组数据
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//static unsigned char ledtube_cnt = 0;
//void sys_ledtube_on2(void)
//{
//	ledtube_cnt++;
//	if(ledtube_cnt>7)
//	{
//		ledtube_cnt = 0;
//	}
//	P0 = 0x00;				//防止切换数码管瞬间有虚影出现
//	P2 = 0x00;
//	P0 = EL[ledtube_cnt];	//取显示数据,段码
//	P2 = ledtube_cnt;  		//取位码
//	
//	//根据人眼适应虚影缓冲时间为50ms左右
//	//我们调整delay在500以下可以看到明显的看起来是一串数据一起显示
//	delay(100); 			
//}/********************************************************
函数名称:sys_keynum_ledon
函数功能:显示按键数值
入口参数:按键数值
出口参数:
修    改:
内    容:
********************************************************/
void sys_keynum_ledon(unsigned char num,unsigned char pn)
{//根据原理图,将P0口全部输出高电平,P2选择0号数码管P0 = 0x00;		//防止切换数码管瞬间有虚影出现P2 = pn;  		//取位码P0 = EL[num];	//取显示数据,段码
}

//c51_ledtube.h文件

#ifndef __C51_LEDTUBE_H__
#define __C51_LEDTUBE_H__extern unsigned char const EL[];//extern void sys_ledtube_on1(void);
//extern void sys_ledtube_on2(void);extern void sys_keynum_ledon(unsigned char num,unsigned char pn);#endif

3.4 外部中断程序

实现在有数据过来时,下降沿触发解码程序。

//c51_exit.c文件

#include "includes.h"void sys_exit_init(void)
{IT0=1;         //边沿触发EX0=1;         //外部中断0开IE0=0;		   //中断标志清零//PX0 = 1;		 //中断优先级不配置EA = 1;//EX1=1;         //外部中断1开//IT1=0;         //电平触发//IT1=1;         //边沿触发,IT1=0表示电平触发
}/*------------------------------------------------外部中断程序
------------------------------------------------*/
void Exit0_isr(void) interrupt 0
{IE0=0;		   //中断标志清零sys_nec_test();
}/*------------------------------------------------外部中断程序
------------------------------------------------*/
void Exit1_isr(void) interrupt 2
{//在此处可以添加去抖动程序,防止按键抖动造成错误//P1=~P1;
}

//c51_exit.h文件

#ifndef __C51_EXIT_H__
#define __C51_EXIT_H__extern void sys_exit_init(void);
extern void Exit0_isr(void);
extern void Exit1_isr(void);#endif

3.5 串口打印程序

实现printf打印不同的字符串。

//c51_uart.c文件

#include "includes.h"/*-----------------------------------------------名称:串口通信内容:连接好串口或者usb转串口至电脑,下载该程序,打开电源打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入 hello,I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确
------------------------------------------------*//******************************************************************/
void sys_uart_init(void)
{SCON  = 0x50;		        /* SCON: 模式 1, 8-bit UART, 使能接收         */TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */TH1   = 0xFD;               /* TH1:  reload value for 9600 baud @ 11.0592MHz   */TR1   = 1;                  /* TR1:  timer 1 run                          */EA    = 1;                  /*打开总中断*///ES    = 1;                  /*打开串口中断*///当使用串口协议通讯时可以使用此型号中断}void Uart_SendChar(unsigned char  dat)
{SBUF = dat; while(!TI); TI = 0; 
}char putchar(char c)//重定向
{Uart_SendChar(c);return c;}/******************************************************************/
/*                  串口中断程序                                  */
/******************************************************************/static unsigned char uart_temp = 0;          //定义临时变量 
static unsigned char uart_cnt = 0;          //定义临时变量 void UART_isr(void) interrupt 4 //串行中断服务程序
{if(RI)                        //判断是接收中断产生{RI=0;                      //标志位清零uart_temp=SBUF;                 //读入缓冲区的值if(uart_cnt==0){if(0x02 == uart_temp){uart_cnt = 1;}else{uart_cnt = 0;}}else if(uart_cnt==1){if(0x05 == uart_temp){uart_cnt = 2;}else{uart_cnt = 0;}}else if(uart_cnt==2){uart_cnt = 0;//P1=uart_temp;                   //把值输出到P1口,用于观察SBUF=uart_temp;                 //把接收到的值再发回电脑端}else{uart_cnt = 0;}}if(TI)                        //如果是发送标志位,清零{TI=0;}
} 

//c51_uart.h文件

#ifndef __C51_UART_H__
#define __C51_UART_H__extern void Uart_SendChar(unsigned char  dat);
extern char putchar(char c);//重定向extern void sys_uart_init(void);
extern void UART_isr(void);#endif

3.6 步进电机程序

//“c51_28byj48.c” 文件

#include "includes.h"bit byj48_type = 0;
unsigned int byj48_value = 0;(1)单4拍控制方式
脉冲电平循环发送的方式控制:
//unsigned char code F_Rotation[4]={0x02,0x04,0x08,0x10}; //正转表格,换算成二进制 0000 0010,0000 0100,0000 1000,0001 0000
//unsigned char code B_Rotation[4]={0x10,0x08,0x04,0x02}; //反转表格,换算成二进制 0001 0000,0000 1000,0000 0100,0000 0010//(2)双4拍控制方式
//AC互补,BD互补的方式进行控制:
//脉冲电平循环发送的方式控制:
unsigned char code F_Rotation[4]={0x09,0x03,0x06,0x0C}; //正转表格
unsigned char code B_Rotation[4]={0x0C,0x06,0x03,0x09}; //反转表格(3)8拍控制方式
正转的步进次序如下:AB组 → BC组 → CD组 → DA组(每个脉冲使电机正转5.625/64度)。
反转的步进次序如下:AB组 → AD组 → CD组 → CB组(每个脉冲使电机正转5.625/64度)。
//unsigned char code F_Rotation[4]={0x03,0x06,0x0c, 0x09}; //正转表格
//unsigned char code B_Rotation[4]={0x03,0x09,0x0c,0x06};//反转表格void sys_28byj48_func(bit type,unsigned int value)
{unsigned char i = 0; if(type){for(i=0;i<4;i++)      //4相{P1=F_Rotation[i];  //输出对应的相 可以自行换成反转表格delay(value);        //改变这个参数可以调整电机转速 ,数字越小,转速越大}}else{for(i=0;i<4;i++)      //4相{P1=B_Rotation[i];  //输出对应的相 可以自行换成反转表格delay(value);        //改变这个参数可以调整电机转速 ,数字越小,转速越大}}
}

//c51_28byj48.h文件

#ifndef __C51_28BYJ48_H__
#define __C51_28BYJ48_H__extern bit byj48_type;
extern unsigned int byj48_value;extern void sys_28byj48_func(bit type,unsigned int value);#endif

3.7 演示效果

(1)串口打印效果

在这里插入图片描述

(2)步进电机实物链接图

在这里插入图片描述

4 设计总结

这种基于STC89C52的遥控器控制步进电机转速和转向操作并通过printf打印信息的系统可以在许多实际场景中发挥作用。以下是一些可能的应用场景:

  1. 智能家居系统:通过遥控器控制步进电机来控制家居窗帘、门禁系统、智能灯光等,实现智能家居的自动化和远程控制。
  2. 监控摄像头:控制监控摄像头的方向和转速,实现对特定区域的监控和跟踪,通过遥控器实现方向控制。
  3. 无人机:控制无人机的方向和高度调整,通过遥控器控制飞行器的移动和姿态调整。
  4. 工业自动化:控制工业机器人的运动,包括转向和速度,用于自动化生产线上的操作。
  5. 车载设备:应用于车载电动窗、天窗、座椅等部件的控制,通过遥控器实现车内设备的远程操作。
  6. 教育示范:用于教学示范,展示遥控器对步进电机的控制原理,以及如何通过单片机实现远程控制。
  7. 科研实验:在实验室环境中用于控制实验设备的转向和速度,如旋转式台盘、转动平台等。
  8. 娱乐设备:应用于模型车、模型船等遥控玩具的控制,实现远程控制玩具车辆的转向和速度。
    以上是一些可能的应用场景,这种系统可以在很多需要远程控制步进电机的场合发挥作用。根据具体需求和场景的不同,系统可能需要进行适当的定制和调整。希望这些应用场景能够启发您,为您的项目提供一些灵感。如果您有任何进一步的问题或需要更多帮助,请随时告诉我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/50564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

skynet热更新之inject

游戏服务器的热更新是一种常见的需求&#xff0c;skynet可以通过inject的方式&#xff0c;来修改一个服务的消息处理函数&#xff0c;达到热更新的效果。 skynet内置服务debug_console skynet自带了一个调试控制台服务。inject注入代码需要先启动这个服务。 skynet.newservi…

【python】python大学排名数据抓取+可视化(源码+数据集+可视化+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

uart开发调试

1. Uart基本框架 1.1概念 通信系统有两种方式&#xff0c;同步通信和异步通信. 同步通信的典型特征&#xff1a;通信双方公用同一个时钟&#xff0c;发送/接受速率完全一致&#xff0c;通信时需要带时钟信号传输. 异步通信的典型特征&#xff1a;通信双方各自具有独立的时钟…

MyBatis操作数据库 -- 动态SQL

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|Spring &#x1faf5; 与天斗其乐无穷 文章目录 1. 动态SQL<if>标签<trim>标签<where> 标签<set> 标签<foreach> 标签<include>标签注解方式 1. 动态SQL 动态sql能够实现不同条件下的sql拼接 …

jquery+bootstrap实现DOM转图片并下载

&#x1f34a;jquery实现DOM结构转图片并下载 版本介绍&#xff1a; Bootstrap v3.3.7jQuery v3.5.1domToImage.js 根据Bootstrap实现dialog上一步下一步多个弹窗交互进行大肆修改&#xff0c;完善了第二步生成图片的功能与更强的交互 1.、功能说明 重新设置bootstrap主题色 …

DNS应用以及扩展知识

&#xff08;一&#xff09;DNS正向代理 1.首先在DNS服务器上安装bind包&#xff0c;安装环境 此部分参考上一个笔记 2.修改配置文件 vim /etc/named.conf 在配置文件中加上"any;" 3.然后配置/etc/named.rfc1912.zonesw文件 添加选中部分 选中部分有一个file文…

24年第三届钉钉杯大学生大数据挑战赛浅析

需要完整资料&#xff0c;请关注WX&#xff1a;“小何数模”&#xff01; 本次钉钉杯大数据挑战赛的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&#xf…

气膜足球馆:经济高效的室内足球场馆解决方案—轻空间

如果你有一片足球场&#xff0c;想要建一个室内的足球馆&#xff0c;为什么不考虑一下气膜建筑呢&#xff1f;气膜建筑以其独特的优势和高性价比&#xff0c;成为现代体育场馆建设中的一匹黑马。它不仅具有传统建筑无法比拟的经济效益和快速施工优势&#xff0c;还在智能控制、…

vue实现电子签名、图片合成、及预览功能

业务功能&#xff1a;电子签名、图片合成、及预览功能 业务背景&#xff1a;需求说想要实现一个电子签名&#xff0c;然后需要提供一个预览的功能&#xff0c;可以查看签完名之后的完整效果。 需求探讨&#xff1a;后端大佬跟我说&#xff0c;文档我返回给你一个PDF的oss链接…

7.27扣...

知识点补充&#xff1a; 1.StringBuilder StringBuilder 类在 Java 中是一个可变字符序列。与 String 类不同&#xff0c;StringBuilder 可以在创建之后被修改。这意味着你可以向 StringBuilder 对象追加、插入或删除字符&#xff0c;而不需要创建新的对象&#xff08;辅助数…

企业公户验证API如何使用JAVA、Python、PHP语言进行应用

在纷繁复杂的金融与商业领域&#xff0c;确保每笔交易的安全与合规是至关重要的。而企业公户验证API&#xff0c;正是这样一位默默守护的数字卫士&#xff0c;它通过智能化的手段&#xff0c;简化了企业对公账户验证流程&#xff0c;让繁琐的审核变得快捷且可靠。 什么是企业公…

chrome浏览器驱动(所有版本)

chrome浏览器驱动 114之前版本 https://chromedriver.storage.googleapis.com/index.html 125以后 125以后版本下载链接在此&#xff0c;只有后面status是绿色对勾的才可以下载&#xff0c;驱动大版本一致就可以使用&#xff0c;不需版本号一模一样&#xff1b;下载所需版本只…

语言转文字

因为工作原因需要将语音转化为文字&#xff0c;经常搜索终于找到一个免费的好用工具&#xff0c;记录下使用方法 安装Whisper 搜索Colaboratory 右上方链接服务 执行 !pip install githttps://github.com/openai/whisper.git !sudo apt update && sudo apt install f…

高性能 Java 本地缓存 Caffeine 框架介绍及在 SpringBoot 中的使用

在现代应用程序中&#xff0c;缓存是一种重要的性能优化技术&#xff0c;它可以显著减少数据访问延迟&#xff0c;降低服务器负载&#xff0c;提高系统的响应速度。特别是在高并发的场景下&#xff0c;合理地使用缓存能够有效提升系统的稳定性和效率。 Caffeine 是一个高性能的…

《程序猿入职必会(4) · Vue 完成 CURD 案例 》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【C++刷题】优选算法——队列+宽搜

N 叉树的层序遍历 vector<vector<int>> levelOrder(Node* root) {vector<vector<int>> ret;if (root nullptr) return ret;queue<Node*> q;q.push(root);ret.push_back({root->val});int size 1;while (!q.empty()) {vector<int> v…

【机器学习】Jupyter Notebook如何使用之基本步骤和进阶操作

引言 Jupyter Notebook 是一个交互式计算环境&#xff0c;它允许创建包含代码、文本和可视化内容的文档 文章目录 引言一、基本步骤1.1 启动 Jupyter Notebook1.2 使用 Jupyter Notebook 仪表板1.3 在笔记本中工作1.4 常用快捷键1.5 导出和分享笔记本 二、进阶用法2.1 组织笔…

从零开始学习网络安全渗透测试之基础入门篇——(二)Web架构前后端分离站Docker容器站OSS存储负载均衡CDN加速反向代理WAF防护

Web架构 Web架构是指构建和管理Web应用程序的方法和模式。随着技术的发展&#xff0c;Web架构也在不断演进。当前&#xff0c;最常用的Web架构包括以下几种&#xff1a; 单页面应用&#xff08;SPA&#xff09;&#xff1a; 特点&#xff1a;所有用户界面逻辑和数据处理都包含…

劝你不要上自动化立体库,非要上,砸锅了吧

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 在当今这个科技日新月异的时代&#xff0c;自动化立体库作为仓储物流领域的佼佼者&#xff0c;以其高效、精准、节省人力的优势&#xff0c;吸引…

Windows下帆软BI(finebi)单机部署移植(Tomcat)攻略

一、基础环境 操作系统&#xff1a;Windows 10 64bit 帆软BI 版本&#xff1a;V9.0/V10.0 HTTP工具&#xff1a;Tomcat 外置数据库&#xff1a;Oracle 11g 实验内容&#xff1a;将已经部署好的帆软BI从一台电脑移植到另一台电脑 二、前期准备 1、做好外置数据库移植&…