📄 rainwiper v10b.c
字号:
/********************************
名称:雨刷控制器
日期: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 + -