/************************************************************************
函数定义
************************************************************************/
#include <C8051F120.h> // SFR declarations
#define SYSTEMCLOCK 22118400L
int i;
/************************************************************************
函数定义
************************************************************************/
void OSCILLATOR_Init (void);
void PORT_Init (void);
void Timer0_Init(void);
void PWM_PORT_Init (void);
void PWM_PCA_Init();
void move(char state,char speed);
void delay();
int main()
{
WDTCN = 0XDE;
WDTCN = 0XAD; //关开门狗必须注意
OSCILLATOR_Init (); //初始化晶振
Timer0_Init(); //初始化定时器
PWM_PORT_Init(); //初始化pwm输出io口
PWM_PCA_Init(); //初始化pca
while (1)
{
move(2,200);
move(3,200);
delay();
delay();
}
}
/*****************************************************************
振荡器初始化
*****************************************************************/
void OSCILLATOR_Init (void)
{
int i; // Software timer
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = CONFIG_PAGE; // Set SFR page
OSCICN = 0x80; // Set internal oscillator to run
// at its slowest frequency
CLKSEL = 0x00; // Select the internal osc. as
// the SYSTEMCLOCK source
// Initialize external crystal oscillator to use 22.1184 MHz crystal,初始化外部晶体振荡器,使用22.1184 MHz晶体
OSCXCN = 0x67; // Enable external crystal osc.
CLKSEL = 0x01; //输出为SYSCLK时不分频,SYSCLK来自外部晶体振荡器
for (i=0; i < 256; i++); // Wait at least 1ms
//OSCXCN = OSCXCN|0x80 ;
while (!(OSCXCN & 0x80)); // Wait for crystal osc to settle
SFRPAGE = LEGACY_PAGE;
FLSCL |= 0x30; // Initially set FLASH read timing for
// 100MHz SYSTEMCLOCK (most conservative
// setting)
if (SYSTEMCLOCK <= 25000000) {
// Set FLASH read timing for <=25MHz
FLSCL &= ~0x30;
} else if (SYSTEMCLOCK <= 50000000) {
// Set FLASH read timing for <=50MHz
FLSCL &= ~0x20;
} else if (SYSTEMCLOCK <= 75000000) {
// Set FLASH read timing for <=75MHz
FLSCL &= ~0x10;
} else { // set FLASH read timing for <=100MHz
FLSCL &= ~0x00;
}
// Start PLL for 50MHz operation
/* SFRPAGE = PLL0_PAGE;
PLL0CN = 0x04; // Select EXTOSC as clk source
PLL0CN |= 0x01; // Enable PLL power
PLL0DIV = 0x01; // Divide by 4
PLL0FLT &= ~0x0f;
PLL0FLT |= 0x01; // Set Loop Filt for (22/4)MHz input clock
PLL0FLT &= ~0x30; // Set ICO for 30-60MHz
PLL0FLT |= 0x00;
PLL0MUL = 0x04; // Multiply by 9
// wait at least 5us
for (i = 0; i < 256; i++) ;
PLL0CN |= 0x02; // Enable PLL
while (PLL0CN & 0x10 == 0x00); // Wait for PLL to lock
*/
SFRPAGE = CONFIG_PAGE;
CLKSEL = 0x01; // Select PLL as SYSTEMCLOCK source
SFRPAGE = SFRPAGE_SAVE; // Restore SFRPAGE
}
void PWM_PORT_Init (void)
{
char SFRPAGE_save = SFRPAGE; // Save Current SFR page
SFRPAGE = CONFIG_PAGE; // Set SFR Page
XBR0 = 0x20;
XBR2 = 0x40;
P0MDOUT = 0xff; // Set p0 to push-pull
SFRPAGE = SFRPAGE_save; // Restore SFR Page
}
void PWM_PCA_Init()
{
char SFRPAGE_save = SFRPAGE; // Save current SFR Page
SFRPAGE = PCA0_PAGE;
PCA0CN = 0; //标志位全部清零,禁止pca定时器
PCA0MD = 0x04; //使用定时器0溢出作为时基,关pca定时器中断,230400/256=900hz
/*PCA0*/
PCA0CPM0 = 0x42; // Module 0 = 8-bit PWM mode,左轮正转pwm
PCA0CPH0 = 0xff; //设置初始占空比为0
/*PCA1*/
PCA0CPM1 = 0x42; // Module 0 = 8-bit PWM mode,左轮反转pwm
PCA0CPH1 = 0xff; //设置初始占空比为0
/*PCA2*/
PCA0CPM2 = 0x42; // Module 0 = 8-bit PWM mode,右轮正转pwm
PCA0CPH2 = 0xff; //设置初始占空比为0
/*PCA3*/
PCA0CPM3 = 0x42; // Module 0 = 8-bit PWM mode,右轮反转pwm
PCA0CPH3 = 0xff; //设置初始占空比为0
CR = 1; //PCA开始工作
SFRPAGE = SFRPAGE_save;
}
/****************************************************
小车移动控制---------正转指的车轮是顺时针旋转,反转相反
1.uint state
state 电机状态
1 右轮正转
2 左轮反转
3 右轮反转
4 左轮正转
2.uint speed 范围0~256,即由其占空比决定
*****************************************************/
void move(char state,char speed)
{
speed=255-speed;
switch(state)
{
case 1:
{
if(!speed) //如果速度为0则占空比为0
{
PCA0CPL0 = 0Xff; //向PCA0CPL0写入数据时会将ECOM0清零
}
PCA0CPH0 = speed; //向PCA0CPH0写入数据时会将ECOM0置一
PCA0CPL1 = 0Xff;
break;
}
case 2:
{
if(!speed) //如果速度为0则占空比为0
{
PCA0CPL1 = 0Xff; //向PCA0CPL0写入数据时会将ECOM0清零
}
PCA0CPH1 = speed; //向PCA0CPH0写入数据时会将ECOM0置一
PCA0CPL0 = 0Xff;
break;
}
case 3:
{
if(!speed) //如果速度为0则占空比为0
{
PCA0CPL2 = 0Xff; //向PCA0CPL0写入数据时会将ECOM0清零
}
PCA0CPH2 = speed; //向PCA0CPH0写入数据时会将ECOM0置一
PCA0CPL3 = 0Xff;
break;
}
case 4:
{
if(!speed) //如果速度为0则占空比为0
{
PCA0CPL3 = 0Xff; //向PCA0CPL0写入数据时会将ECOM0清零
}
PCA0CPH3 = speed; //向PCA0CPH0写入数据时会将ECOM0置一
PCA0CPL2 = 0Xff;
break;
}
default: break;
}
}
void delay()
{
int i,j,k;
for(i=0;i<=100;i++)
for(j=0;j<=100;j++)
for(k=0;k<=1000;k++) ;
}
void Timer0_Init(void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = TIMER01_PAGE; // Set SFR page
TH0 = 0xfe; // Init Timer0 High register,460800hz/2=230400hz
TL0 = TH0; // Set the intial Timer0 value
TMOD = 0x02; // Timer0 in 8-bit reload mode
CKCON = 0x02; // Timer0 uses a 1:48 prescaler,22.1184mhz/48=460800hz=460.8khz
//ET0=1; // Timer0 interrupt enabled
TCON = 0x10; // Timer0 ON
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}