|
/**********************
舵機(jī)控制PWM/按鍵控制/LED顯示
V1.0版
******************************************/
#include "STC15W40XXX.H"
#include "intrins.h"
//定義主時(shí)鐘
#define FOSC 33177600UL
#define T1000Hz (FOSC / 12 / 1000)
#define CCP_S0 0x10 //P_SW1.4
#define CCP_S1 0x20 //P_SW1.5
//************** PWM8 變量和常量以及IO口定義 ***************
//******************** 6通道8 bit 軟PWM ********************
sbit P_PWM6 = P3^4; // 舵機(jī)1 PWM定義IO
sbit P_PWM5 = P3^5; // 舵機(jī)2 PWM定義IO
sbit P_PWM4 = P3^6; // 舵機(jī)3 PWM定義IO
sbit P_PWM3 = P2^0;
sbit P_PWM2 = P2^1;
sbit P_PWM1 = P2^2;
sbit LED1 = P2^3;
sbit LED2 = P2^4;
sbit LED3 = P2^5;
sbit LED4 = P2^6;
sbit LED5 = P2^7;
sbit LED6 = P1^0;
sbit Key1=P5^5; //單個(gè)舵機(jī)轉(zhuǎn)動(dòng)
sbit Key2=P5^4; //全部舵機(jī)轉(zhuǎn)動(dòng)
sbit Key3=P1^7; //復(fù)位按鍵
bit Reset=0;
uint P1_11us=0;
uint cnt;
uint value;
uchar K1_cont=0;
uchar K2_cont=0;
unsigned char j;
unsigned char KeySta[3] = { 1, 1, 1 }; //全部按鍵的當(dāng)前狀態(tài)
unsigned char backup[3] = { 1, 1, 1 }; //按鍵值備份,保存前一次的值
uint Ptem_angle[6]={90,90,90,90,90,90}; //6個(gè)舵機(jī)臨時(shí)存儲(chǔ)角度(在0-180內(nèi))
uint SetP_angle[6] ={90,90,90,90,90,90}; //6個(gè)設(shè)定舵機(jī)轉(zhuǎn)動(dòng)角(0-180)(11us*(45-225)=0.5ms -2.5ms
//--------------------
void UartInit(); [url=]//9600bps@33.1776MHz[/url]
void Timer0Init(); //Timer0 set
void PCATimerInit(); //Timer0 set
void Key_scan(); //按鍵掃描函數(shù)
void Key_Function(); //按鍵功能函數(shù)
void LDE_Shew(); //LED顯示函數(shù)
void Motor_Run(); //LED顯示函數(shù)
void Delay500ms() [url=]//@33.1776MHz[/url]
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 64;
j = 9;
k = 179;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/**********************************************/
void main()
{
PCATimerInit(); //PCA定時(shí)器初始化
Timer0Init(); //定時(shí)器0初始化
UartInit(); //串口初始化
EA = 1; //打開總中斷
Delay500ms();
while(1)
{
Key_Function();
LDE_Shew();
}
}
/********************** Timer0 11us中斷函數(shù) ************************/
//為什么要定義11us的中斷,因?yàn)?0ms的周期信號控制舵機(jī)轉(zhuǎn)動(dòng),0.5-2.5中,只有2ms時(shí)間高電平控制0-180的角度。
//因此轉(zhuǎn)動(dòng)1度時(shí),需要11us的時(shí)間(一次中斷產(chǎn)生),180度需要1980us,約2MS,例如轉(zhuǎn)動(dòng)90度是1.5MS高和18.5的低,
//一個(gè)周期20ms產(chǎn)生1800次的中斷,其中90+45=135次中斷為高,1800-135=1665次為低。循環(huán)得到結(jié)果
void timer0 (void) interrupt 1
{
switch (K1_cont)
{
case 0: P_PWM1=0; break;
case 1: Motor_Run(); P_PWM2= P_PWM3= P_PWM4= P_PWM5= P_PWM6= 0;
if(P1_11us<=Ptem_angle[K1_cont-1]) { P_PWM1 = 1; } else { P_PWM1 = 0; } break;
case 2: Motor_Run(); P_PWM1=P_PWM3=P_PWM4=P_PWM5=P_PWM6= 0;
if(P1_11us<=Ptem_angle[K1_cont-1]) { P_PWM2 = 1; } else { P_PWM2 = 0; } break;
case 3: Motor_Run(); P_PWM1 =P_PWM2=P_PWM4=P_PWM5=P_PWM6= 0;
if(P1_11us<=Ptem_angle[K1_cont-1]) { P_PWM3 = 1; } else { P_PWM3 = 0; } break;
case 4: Motor_Run(); P_PWM1 =P_PWM2=P_PWM3=P_PWM5=P_PWM6= 0;
if(P1_11us<=Ptem_angle[K1_cont-1]) { P_PWM4 = 1; } else { P_PWM4 = 0; } break;
case 5: Motor_Run(); P_PWM1 =P_PWM2=P_PWM3=P_PWM4=P_PWM6=0;
if(P1_11us<=Ptem_angle[K1_cont-1]) { P_PWM5 = 1; } else { P_PWM5 = 0; } break;
case 6: Motor_Run(); P_PWM1=P_PWM2=P_PWM3= P_PWM4= P_PWM5=0;
if(P1_11us<=Ptem_angle[K1_cont-1]) { P_PWM6 = 1; } else { P_PWM6 = 0; } break;
default: break;
}
}
//PCA定時(shí)器中斷
void PCA_isr() interrupt 7 using 1
{
CCF0 = 0; //清中斷標(biāo)志
CCAP0L = value;
CCAP0H = value >> 8; //更新比較值
value += T1000Hz;
if (cnt-- == 0)
{
cnt = 2000; //記數(shù)1000次
SBUF=0XFF;
}
Key_scan();
}
//*************************************************************************
//UART 串口中斷
void Uart() interrupt 4 using 1
{
if (RI)
{
RI = 0;
}
if (TI)
{
TI = 0; //
}
}
void Key_scan()//按鍵掃描函數(shù)
{
uchar j;
static uchar keybuf[3] = { 0xFF, 0xFF, 0xFF }; //按鍵掃描緩沖區(qū)
//將3 個(gè)按鍵值移入緩沖區(qū)
keybuf[0] = (keybuf[0] << 1) | Key3;
keybuf[1] = (keybuf[1] << 1) | Key2;
keybuf[2] = (keybuf[2] << 1) | Key1;
//消抖后更新按鍵狀態(tài)
for (j=0; j<3; j++) // 3 個(gè)按鍵,所以循環(huán) 3 次
{
if ((keybuf[j] & 0xFF) == 0x00) //連續(xù) 3次掃描值為 0,即 24ms 內(nèi)都是按下狀態(tài)時(shí),可認(rèn)為按鍵已穩(wěn)定的按下
{
KeySta[j] = 0;
}
else
if ((keybuf[j] & 0xFF) == 0xFF)
{ //連續(xù) 4次掃描值為 1,即16ms 內(nèi)都是彈起狀態(tài)時(shí),可認(rèn)為按鍵已穩(wěn)定的彈起
KeySta[j] = 1;
}
}
}
void Key_Function()
{
static bit i=0;
for (j=0; j<3; j++) //依次檢測按鍵
{
if (backup[j] != KeySta[j]) //檢測按鍵動(dòng)作
{
if (backup[j] != 0) //按鍵按下時(shí)執(zhí)行動(dòng)作
{
switch (j)
{
case 0: K2_cont=0; K1_cont++; if(K1_cont>=7) K1_cont=0;
break;
case 1:
if(!i)
{
SetP_angle[K1_cont-1]-=10;
if(SetP_angle[K1_cont-1]<=45)
{
i=!i;
}
}
else
{
SetP_angle[K1_cont-1]+=10;
if(SetP_angle[K1_cont-1]>=170)
{
i=!i;
}
}
break;
case 2:
break;
default: break;
}
}
backup[j] = KeySta[j]; //更新前一次的備份值
}
}
}
//
//////LEDf顯示函數(shù)
void LDE_Shew()
{
switch (K1_cont)
{
case 0: LED1=LED2=LED3=LED4=LED5=LED6=1; break;
case 1: LED1=LED2=LED3=LED4=LED5=LED6=1; LED1=0; break;
case 2: LED1=LED2=LED3=LED4=LED5=LED6=1; LED2=0; break;
case 3: LED1=LED2=LED3=LED4=LED5=LED6=1; LED3=0; break;
case 4: LED1=LED2=LED3=LED4=LED5=LED6=1; LED4=0; break;
case 5: LED1=LED2=LED3=LED4=LED5=LED6=1; LED5=0; break;
case 6: LED1=LED2=LED3=LED4=LED5=LED6=1; LED6=0; break;
default: break;
}
}
void Motor_Run()
{
P1_11us++; //一次中斷,自加一次
if (P1_11us>1800) //20ms執(zhí)行以下程序
{
P1_11us=0; //清0
if(Ptem_angle[K1_cont-1]>=(SetP_angle[K1_cont-1]+40))
{
Ptem_angle[K1_cont-1]--; //自加一次角度,電機(jī)緩慢運(yùn)行,在設(shè)定的角度內(nèi)反復(fù)轉(zhuǎn)動(dòng),如0-90度
}
else
{
Ptem_angle[K1_cont-1]++;
}
}
}
//******************串口初始化
void UartInit(void) [url=]//9600bps@33.1776MHz[/url]
{
SCON = 0x50; //8位數(shù)據(jù),可變波特率
AUXR |= 0x01; //串口1選擇定時(shí)器2為波特率發(fā)生器
AUXR &= 0xFB; //定時(shí)器2時(shí)鐘為Fosc/12,即12T
T2L = 0xB8; //設(shè)定定時(shí)初值
T2H = 0xFF; //設(shè)定定時(shí)初值
AUXR |= 0x10; //啟動(dòng)定時(shí)器2
ES=1; //允許串口中斷
}
//定時(shí)器T0用作脈沖發(fā)生器,定時(shí)11us
void Timer0Init(void) //11微秒@33.1776MHz
{
AUXR |= 0x80; //定時(shí)器時(shí)鐘1T模式
TMOD &= 0xF0; //設(shè)置定時(shí)器模式
TL0 = 0x8F; //設(shè)置定時(shí)初值
TH0 = 0xFE; //設(shè)置定時(shí)初值
TF0 = 0; //清除TF0標(biāo)志
TR0 = 1; //定時(shí)器0開始計(jì)時(shí)
ET0=1; //中斷允許
}
//PCA定時(shí)器設(shè)置 定時(shí)1MS
void PCATimerInit()
{
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=0
P_SW1 = ACC; //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)
CCON = 0; //初始化PCA控制寄存器
//PCA定時(shí)器停止 清除CF標(biāo)志 清除模塊中斷標(biāo)志
CL = 0; //復(fù)位PCA寄存器
CH = 0;
CMOD = 0x00; //設(shè)置PCA時(shí)鐘源
//禁止PCA計(jì)數(shù)器中斷
value = T1000Hz;
CCAP0L = value;
CCAP0H = value >> 8; //初始化PCA模塊0
value += T1000Hz;
CCAPM0 = 0x49; //PCA模塊0為16位定時(shí)器模式
CR = 1; //PCA定時(shí)器開始工作
cnt = 0;
}
|
評分
-
查看全部評分
|