/************************************************************
* PWM Controler .c File
* date:2018-7-24
* author:Jack Lam
* ver:0.1
***************************************************************/
//TODO: 红光PWM增加模式5.1-5.4K 占空比7:3
//TODO :获取内部bandgap电压ADC值间接计算供电电压
#include <stdio.h>
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_Define.h"
#include "Led.h"
/*
使用方法:
1.修改两个通道的PWM占空比和周期 (PWM1输出引脚:P12 PWM2输出引脚 P10),设置OOL触发的电压值。
2.KEY1 用于三个输出模式的切换,下降沿触发 按键引脚 P00
3.Lock 用于锁定输出,OOL无效
4.OOL 触发的时候,停止所有输出
*/
/*修改以下参数至符合要求*/
#define PWM_Freq 5100 /*频率 Hz */
#define PWM1_DUTY 50 /*占空比 0-100*/
#define PWM2_DUTY 50 /*占空比 0-100*/
#define OOL_TrigVal 1 /*设置OOL触发的电压值*/
#define OOL_Direction 1 /*0 :低于00L电压的时候触发OOL 1:高于OOL电压时触发电压*/
/* System variable don't modify*/
char Mode=0;
sbit DC_SW = P1^5;
sbit KEY_MODE = P1^1;
sbit KEY_LOCK =P1^4;
/*0 通道1,通道2 都有PWM输出*/
/*1 只有通道1 PWM输出*/
/*2 只有通道2 PWM输出*/
uint16_t TrigADC = 0;/*上电更新,作为比较值*/
uint8_t Lock_Status = 0;/*0:未开启,1:开启*/
/*Declare*/
uint8_t isOOL();
//改变输出模式
void Change_Mode(char mode)
{
switch(mode)
{
case 0:
PWM0_P12_OUTPUT_ENABLE;P12=1;
PWM2_P10_OUTPUT_ENABLE;P10=1;
Led_On(LED_Vertical);
Led_On(LED_Horizontal);
break;
case 1:
PWM0_P12_OUTPUT_DISABLE;P12=0;
PWM2_P10_OUTPUT_ENABLE;P10=1;
Led_Off(LED_Vertical);
Led_On(LED_Horizontal);
break;
case 2:
PWM0_P12_OUTPUT_ENABLE;P12=1;
PWM2_P10_OUTPUT_DISABLE;P10=0;
Led_On(LED_Vertical);
Led_Off(LED_Horizontal);
break;
}
}
/*
*函数名称:按键中断处理函数
*函数功能:接收到按键中断后进行PWM输出模式切换
*
*/
void PinInterrupt_ISR (void) interrupt 7
{
if(PIF&1<<1)
{
PIF &= ~(1<<1);
Timer0_Delay1ms(30);
if(KEY_MODE!=0||(Lock_Status==0&&isOOL()))/*防抖,未锁定且OOL的时候*/
return;
Mode=(++Mode)>2?0:Mode; /*切换输出模式*/
Change_Mode(Mode);
}
else if(PIF&1<<4)
{
PIF &= ~(1<<4);
Timer0_Delay1ms(30);
if(KEY_LOCK!=0)/*防抖*/
return;
Lock_Status=!Lock_Status;
if(Lock_Status)//锁定
{
Change_Mode(Mode);
Led_On(LED_Lock);
Led_Off(LED_OOL);//关闭OOL灯,防止冲突
}
else//解锁
{
Led_Off(LED_Lock);
}
}
}
/*
*函数名称:配置IO脚中断
*
*/
void IntterruptSetting()
{
P11_Input_Mode;
P14_Input_Mode;
P11_Quasi_Mode;//使用准双向模式
P14_Quasi_Mode;
P11=1;
P14=1;
Enable_INT_Port1;
Enable_BIT1_FallEdge_Trig;
Enable_BIT4_FallEdge_Trig;
set_EPI; // Enable pin interrupt
set_EA; // global enable bit
}
/*
*函数名称:设置PWM频率
*
*/
void Set_Pwm(long Freq,long Duty_Cycle1,long Duty_Cycle2)
{
/**********************************************************************
以 PWMPH = 0x07; PWMPL = 0xCF;为例
PWM frequency = Fpwm/((PWMPH,PWMPL) + 1) <Fpwm = Fsys/PWM_CLOCK_DIV>
= (16MHz/8)/(0x7CF + 1)
= 1KHz (1ms)
***********************************************************************/
long PWMP_Value;
PWMP_Value = 2000000/Freq-1;
PWMPH = PWMP_Value>>8; /*设置周期 类似Cortex M3的定时器重载值*/
PWMPL = PWMP_Value;
PWM0H =(long)((PWMP_Value+1)*((float)Duty_Cycle1/100))>>8;/*设置占空比*/
PWM0L =(PWMP_Value+1)*((float)Duty_Cycle1/100);
PWM2H =(long)((PWMP_Value+1)*((float)Duty_Cycle2/100))>>8;
PWM2L =(PWMP_Value+1)*((float)Duty_Cycle2/100);
set_LOAD;
set_PWMRUN;
}
//ADC初始化
void ADC_Init()
{
Enable_ADC_AIN1;
TrigADC = OOL_TrigVal*4095/3.3;
}
//获取ADC数值
uint16_t ADC_GetVal()
{
uint16_t result;
Enable_ADC_AIN1;
clr_ADCF;
set_ADCS;
while(ADCF==0);
result=ADCRH;
result<<=4;
result+=ADCRL;
return result;
}
//初始化定时器3,并让其运行,每100ms中断一次
//持续中断5秒,每次让PWM更新重装值调整占空比
void Timer3_Run_100ms()
{
T3CON = 0x07; //128分频
RL3 = LOBYTE(TIMER_DIV128_VALUE_100ms);
RH3 = HIBYTE(TIMER_DIV128_VALUE_100ms);
set_EA;
set_ET3;
set_TR3;
}
//定时器3中断
void TIM3_Interrupt (void) interrupt 16
{
static char time=0;//中断的次数
long Duty_Cycle1,Duty_Cycle2; //PWM频率
time++;
Duty_Cycle1=PWM1_DUTY+(100-PWM1_DUTY)/50*time;//5秒后完成
Duty_Cycle2=PWM2_DUTY+(100-PWM2_DUTY)/50*time;
Set_Pwm(PWM_Freq,Duty_Cycle1,Duty_Cycle2);
if(time>=50)//完成,关闭不再调整
clr_TR3;
}
uint8_t isOOL()
{
#if OOL_Direction==0
if(ADC_GetVal()<=TrigADC)
#else
if(ADC_GetVal()>=TrigADC)
#endif
{
return 1;
}
else
return 0;
}
/************************************************************************************************************
* Main function
************************************************************************************************************/
void main(void)
{
InitialUART0_Timer3(9600); //UART0 Baudrate from Timer1
Set_All_GPIO_Quasi_Mode;
DC_SW=1;
PWM0_P12_OUTPUT_ENABLE;
PWM2_P10_OUTPUT_ENABLE;
PWM_IMDEPENDENT_MODE;
PWM_CLOCK_DIV_8;
Set_Pwm(PWM_Freq,PWM1_DUTY,PWM2_DUTY);
Change_Mode(Mode);
Timer3_Run_100ms();
IntterruptSetting();
ADC_Init();
LED_Init();
while(1)
{
if(Lock_Status==1)/*锁定输出触发的时候,不管OOL状态*/
continue;
if(isOOL())
{
Led_On(LED_OOL);
PWM0_P12_OUTPUT_DISABLE;P12=0;//关闭输出
PWM2_P10_OUTPUT_DISABLE;P10=0;
Led_Off(LED_Vertical);
Led_Off(LED_Horizontal);
}
else
{
Led_Off(LED_OOL);
Change_Mode(Mode); //恢复输出
};
Timer1_Delay1ms(10);
}
}
|