⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rainwiper v10b

📁 用L293步进电机驱动芯片做的步进电机驱动器.
💻
字号:
/********************************
名称:雨刷控制器
日期:2007-06-23
作者:Mavinger
版本:
V1.0:2007-07-8 ,创建此版本

V2.0:2006-11-5 ,修改外部晶振为11.0592M


硬件:
1.控制单片机: 12C5052AD
2.步进电机驱动器: L293D




********************************/

#include "STC12C2052AD.h"
#include <INTRINS.h>
#include <math.h>
#include <stdio.h>

//数据类型定义
typedef unsigned char byte;
typedef unsigned int  word;
typedef unsigned long dword;


//#define  Timer_H    0xFF		//0.1ms
//#define  Timer_L    0xBD
#define  Timer_H    0xFF		//0.01ms
#define  Timer_L    0xF9



//电机驱动控制

//input
sbit Run_Mode	=P3^5; 
sbit Stop_Mode	=P3^4;
sbit Speed_Mode	=P3^3;

//output
sbit Step_EN1	=P1^7;
sbit Step_EN2	=P1^6;

sbit Out_A0  	=P1^3;
sbit Out_A1     =P1^2; 
sbit Out_B0     =P1^1; 
sbit Out_B1     =P1^0; 


#define Open	1
#define Close   0
#define ON      1
#define OFF     0

#define OK  1
#define Error 0

/*---MCU Type---*/                   
#define AP_Memory_Begin_Sector_addr		  0x0000
#define AP_Memory_End_Sector_addr         0x7e00
#define AP_Memory_End_Byte_addr           0x7fff

#define Data_Memory_Begin_Sector_addr     0x8000
#define Data_Memory_End_Sector_addr       0xf600
#define Data_Memory_End_Byte_addr         0xf7ff

/*---命令---*/
#define READ_Data_Memory_Command			 0x01     /*  字节读应用程序区和数据存储区   */
#define PROGRAM_Data_Memory_Command          0x02        /*  字节编程应用程序区和数据存储区 */
#define SECTOR_ERASE_Data_Memory_Command     0x03        /*  扇区擦除应用程序区和数据存储区 */

#define Wait_Time 0x01      //CPU等待时间 20M:0x01    40M: 0x00

#define In_One_Sector  512    //扇区大小: 512字节

/*------ISP_CONTR -----------*/
#define ResetToISP   0x60    /* MCU 软复位至ISP程序区*/
#define AllowFlash   0x80    /*允许ISP/IAP操作*/
#define StartAtISP   0x40  
#define OnReset      0x20


/*产品参数处于Data Flash的首地址*/
#define IDBLOCK_ORIGIN	0x9400
#define MFBLOCK_ORIGIN  0x9C00
#define POSBLOCK_ORIGIN 0x9800

#define DATAPARA_ORIGIN	0x8A00
#define DATACNT_ORIGIN  0x8C00


bit MotorDir;
bit Runflag,Stopflag;

word stepsave,Degreesave;
byte np;


const byte forward[]=
//{0b10100011,0b11101011,0b11001011,0b11011011,0b10010011,0b11010111,0b11000111,0b11100111,};
//{0xA3,0xEB,0xCB,0xDB,0x93,0xD0,0xC7,0xE7};

//{0b11111000,0b1111010,0b11110010,0b11110110,0b11110100,0b11110101,0b11110001,0b11111001,};
//{0xF8,0xFA,0xF2,0xF6,0xF4,0xF5,0xF1,0xF9};

//{0b10111000,0b1111010,0b01110010,0b11110110,0b10110100,0b11110101,0b01110001,0b11111001,};
{0xB8,0xFA,0x72,0xF6,0xB4,0xF5,0x71,0xF9};



const byte backward[]=
//{0xF9,0xF1,0xF5,0xF4,0xF6,0xF2,0xFA,0xF8};
{0xF9,0x71,0xF5,0xB4,0xF6,0x72,0xFA,0xB8};

void Initial(void)
{
	AUXR=AUXR & 0x7F;  				//T0x12=0; 系统时钟12分频,即 T=12/6=2us
	TMOD=0x01;						//C/T1作定时用,16位模式	
	//定时模式1,10ms
	//0xEC78 : 晶振6M
	//TH0=0xEC;
	//TL0=0x78;
	//0xE5F5 : 晶振8M
	//0xCBEA : 晶振16M
	//定时模式1,1ms	
	//0xFE0C : 晶振6M
	//0xFD65 : 晶振8M
	//TH0=0xFD;
	//TL0=0x65;
	//定时模式1,0.1ms	
	//0xFFCE : 晶振6M
	//0xFFBD : 晶振8M

//	TH0=Timer_H;
//	TL0=Timer_L;

//	ET0=1;
//	EA=1;
//  TR0=1;

	P1M0=0;		//P1M0=0,P1M1=0,P1口为准双向口
	P1M1=0;
	P3M0=0;
	P3M1=0;

}


//1ms*N 延时
void Delay1MS(word delay1ms)
{
	word cnt;
	byte cnt1; 
	

	for(cnt=0;cnt<delay1ms;cnt++)
	{
		for(cnt1=0;cnt1<200;cnt1++)
		_nop_();
	}
}

void MotorRst(void)
{
	Step_EN1=1;
	Step_EN2=1;
	Out_A0=0;
	Out_A1=0;
	Out_B0=0;
	Out_B1=0;
}

void MotorSet(void)
{
//	MotorRst();
//	Delay1MS(2);
//	Step_EN1=1;
//	Step_EN2=1;
//	Out_A0=1;
//	Out_A1=0;
//	Out_B0=0;
//	Out_B1=0;
	P1=0xB8;
	Delay1MS(1);
}


void StepRun(byte StepDir,word Speednum)		// One step run
{

	if(StepDir & 0x01)
	{	 
		MotorDir=1;
		if(np==0)
			np=7;
		else 
			np--;
		P1=forward[np];
		Delay1MS(Speednum);	
	}
	else
	{
		MotorDir=0;
		if(np==0)
			np=7;
		else 
			np--;
		P1=backward[np];
		Delay1MS(Speednum);	
	}		
}

void MotorTurn(byte StepDir,word Speednum,word Degree)	//方向,速度,度数
{
	word degreecnt;
	word stepcnt;

	degreecnt=Degree/0.9;
	Degreesave=degreecnt;	
	
	for(stepcnt=0;stepcnt<degreecnt;stepcnt++,stepsave)
	{
		StepRun(StepDir,Speednum);
	}
}


void MotorReturn(byte StepDir,word Speednum)
{
	word stepcnt;
	word savecnt;

	savecnt=Degreesave-stepsave;

	for(stepcnt=0;stepcnt<savecnt;stepcnt++)
	{
		StepRun(StepDir,Speednum);
	}
}


//---------------------EEPROM --------------------------------

/*------------------
打开ISP/IAP功能
--------------------*/
void ISP_IAP_Enable(void)
{
	EA	=	0;	/* 关中断 */
	ISP_CONTR	=	ISP_CONTR & 0x18;       /* 0001,1000 */
	ISP_CONTR	=	ISP_CONTR | Wait_Time;
	ISP_CONTR	=	ISP_CONTR | 0x80;       /* 1000,0000 */	
}


/*------------------
关闭ISP/IAP功能
--------------------*/
void ISP_IAP_Disable(void)
{
	ISP_CONTR	=	ISP_CONTR & 0x7f;	/* 0111,1111 */
	ISP_TRIG	=	0x00;
	EA			=   1;                	/* 开中断 */
}

/*------------------
字节读
输入: 16位地址
返回: 一个字节数据
说明:
--------------------*/
byte Byte_Read(word byte_addr)
{
	ISP_ADDRH=(byte)(byte_addr >> 8);
	ISP_ADDRL=(byte)(byte_addr & 0x00ff);

	ISP_CMD	=ISP_CMD&0xf8;        // 1111,1000  等待模式
	ISP_CMD	=ISP_CMD|READ_Data_Memory_Command;   //0000,0001 读数据 

	ISP_IAP_Enable();

	ISP_TRIG=0x46;
	ISP_TRIG=0xb9;
	_nop_();

	ISP_IAP_Disable();
	return (ISP_DATA);	
}


void flash_Block_Read(byte *dest, word src, word count)
{
	word idata i;
	
	for(i = 0; i < count; i++)
	{
		*(dest + i) = Byte_Read(src+i);
	}
}

/*------------------
扇区擦除
输入: 16位地址
返回:=1  Erase success
说明:
--------------------*/
byte Sector_erase(word sector_addr)
{
	word idata get_sector_addr	=	0;
	get_sector_addr			=	(sector_addr & 0xfe00); // 1111,1110,0000,0000; 取扇区地址
	ISP_ADDRH        		=	(byte)(get_sector_addr >> 8);
	ISP_ADDRL		        =	0x00;

	ISP_CMD	=	ISP_CMD	&	0xf8;	// 1111,1000 
	ISP_CMD	=	ISP_CMD	| SECTOR_ERASE_Data_Memory_Command;	// 0000,0011 

	ISP_IAP_Enable();
	ISP_TRIG	=	0x46;        // 触发ISP_IAP命令
	ISP_TRIG	=	0xb9;        // 触发ISP_IAP命令 
	 _nop_();
	 _nop_();

	ISP_IAP_Disable();
	return OK;	
}



/*------------------
写数据进 数据Flash存储器, 只在同一个扇区内写,不保留原有数据
begin_addr,被写数据Flash开始地址;counter,连续写多少个字节; array[],数据来源
--------------------*/
byte Sequential_write_flash_in_one_sector(word begin_addr, byte *array, word counter)
{
	word	idata	i	=	0;
	word	idata	in_sector_begin_addr	=	0;
	word	idata sector_addr	=	0;

	// 判是否是有效范围,此函数不允许跨扇区操作 

	if(counter > In_One_Sector)
		return	Error;
	in_sector_begin_addr = begin_addr & 0x01ff;         // 0000,0001,1111,1111 
	if( (in_sector_begin_addr + counter) > In_One_Sector)
		return Error;

    //擦除 要修改/写入 的扇区 
	sector_addr	=	(begin_addr & 0xfe00);	// 1111,1110,0000,0000; 取扇区地址 
	ISP_ADDRH	=	(byte)(sector_addr >> 8);
	ISP_ADDRL	=	0x00;
	ISP_CMD		=	ISP_CMD	&	0xf8;		// 1111,1000 
	ISP_CMD		=	ISP_CMD	|	SECTOR_ERASE_Data_Memory_Command;	// 0000,0011 

	ISP_IAP_Enable();
	ISP_TRIG	=	0x46;        //触发ISP_IAP命令
	ISP_TRIG	=	0xb9;        // 触发ISP_IAP命令 
	_nop_();

	for(i = 0; i< counter; i++)
	{
		//写一个字节
		ISP_ADDRH	=	(byte)(begin_addr >> 8);
		ISP_ADDRL	=	(byte)(begin_addr & 0x00ff);
		ISP_DATA	=	*array;
		ISP_CMD		=	ISP_CMD	&	0xf8;	//1111,1000
		ISP_CMD		=	ISP_CMD	|	PROGRAM_Data_Memory_Command;		//0000,0010

		ISP_TRIG	=	0x46;	// 触发ISP_IAP命令 
		ISP_TRIG	=	0xb9;	// 触发ISP_IAP命令 
		_nop_();
		_nop_();
		                         // 读回来
		ISP_DATA	=	0x00;
		ISP_CMD		=	ISP_CMD	&	0xf8;	// 1111,1000 
		ISP_CMD     =	ISP_CMD	|	READ_Data_Memory_Command;	// 0000,0001
		ISP_TRIG	=	0x46;	// 触发ISP_IAP命令 
		ISP_TRIG	=	0xb9;	// 触发ISP_IAP命令 
		_nop_();
		_nop_();
		//  比较对错 if(ISP_DATA != *array)
		if(ISP_DATA != *array)
		{
			ISP_IAP_Disable();
			return Error;
		
		}
        begin_addr++;
		array++;
	}
	ISP_IAP_Disable();
	return	OK;	
}


main()
{
	word cnt;

	Initial();
		
  Run_Mode=1;
	Stop_Mode=1;
	Speed_Mode=1;
  
  stepsave=0;
  Degreesave=0;

	while(1)
	{	
		if(!Run_Mode)
		{
			Runflag=1;
			if(!Speed_Mode)
			{
				MotorTurn(1,30,350);		//正转
				Delay1MS(50);
				MotorTurn(0,30,350);		//反转
				MotorRst();
			}
			else
			{
				MotorTurn(1,50,350);		//正转
				Delay1MS(50);
				MotorTurn(0,50,350);		//反转
				MotorRst();
			}
		}

		else if(Run_Mode && !Stop_Mode)
		{
			for(cnt=0;cnt<400;cnt++)
				StepRun(1,40);
			MotorRst();
			Delay1MS(2000);
			for(cnt=0;cnt<400;cnt++)
				StepRun(0,40);
			MotorRst();
			Delay1MS(2000);

		}

		else
			MotorSet();


/*
		else if(Run_Mode && Runflag)
		{
			Runflag=0;
			if(MotorDir&0x01)
			{
				//MotorReturn(1,30);		//正转运行,反转返回
				MotorTurn(0,30,350);		//反转
			}
			else
			{
				//MotorReturn(0,30);		//反转运行,正转返回		
				MotorTurn(1,30,350);		//反转		
			}
		}*/
	}
}


void Timer0(void) reentrant  interrupt 1
{

	TH0=Timer_H;
	TL0=Timer_L;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -