开启100us中断
void Time_Init(void)
{
DISI();
//;Initial Timer0
PCON1 = C_TMR0_Dis; // Disable Timer0
TMR0 = 100; // Load 0x00 to TMR0 (Initial Timer0 register)
T0MD = C_PS0_TMR0 | C_PS0_Div2;
INTE = C_INT_TMR0;
PCON1 = C_TMR0_En; // Enable Timer0
ENI(); // Enable all unmasked interrupts
}
开启10ms执行一次main函数
void isr(void) __interrupt(0)
{
if (INTFbits.T1IF)
{
INTF = (char)~(C_INT_TMR1); // Clear T1IF flag bit
}
if (INTFbits.T0IF)
{
INTF = (char)~(C_INT_TMR0); // Clear T0IF flag bit
TMR0 += 158;
ti16_cnt0++;
if (ti16_cnt0 > 99)
{
ti16_cnt0 = 0;
time_10ms_flag = 1;
}
}
}
void main(void)
{
GPIO_Init();
CLRWDT();
ADC_Init();
PWM_Init();
delay(1000);
Time_Init();
while (1)
{
CLRWDT(); // Clear WatchDog
if (time_10ms_flag)
{
time_10ms_flag = 0;
//这里面添加要执行的程序
}
}
}
ADC初始化
PACON寄存器添加要打开的引脚通道
void ADC_Init(void)
{
//----- Initial ADC-----
ADMD = C_ADC_En | C_ADC_CH_Dis | C_Quarter_VDD; // Enable ADC power, Disable global ADC input channel, Select PA0 pad as ADC input (SFR "ADMD")
//----- ADC high reference voltage source select-----
// ADVREFH = C_Vrefh_VDD; // ADC reference high voltage is supplied by internal VDD (Note: ADC clock freq. must be equal or less 2MHz @ VDD=5.0V)
// ADVREFH = C_Vrefh_4V; // ADC reference high voltage is supplied by internal 4V (Note: ADC clock freq. must be equal or less 1MHz)
ADVREFH = C_Vrefh_3V; // ADC reference high voltage is supplied by internal 3V (Note: ADC clock freq. must be equal or less 500KHz)
// ADVREFH = C_Vrefh_2V; // ADC reference high voltage is supplied by internal 2V (Note: ADC clock freq. must be equal or less 250KHz)
//----- ADC clock frequency select----------------------------
ADR = C_Ckl_Div1; // ADC clock=Fcpu/1, Clear ADIF, disable ADC interrupt
// ADR = C_Ckl_Div2; // ADC clock=Fcpu/2, Clear ADIF, disable ADC interrupt
// ADR = C_Ckl_Div8; // ADC clock=Fcpu/8, Clear ADIF, disable ADC interrupt
// ADR = C_Ckl_Div16; // ADC clock=Fcpu/16, Clear ADIF, disable ADC interrupt
//----- ADC Sampling pulse width select-------------
// ADCR = C_Sample_1clk | C_12BIT; // Sample pulse width=1 adc clock, ADC select 12-bit conversion ( Note: ADC clock freq. must be equal or less 500KHz)
// ADCR = C_Sample_2clk | C_12BIT; // Sample pulse width=2 adc clock, ADC select 12-bit conversion ( Note: ADC clock freq. must be equal or less 1MHz)
// ADCR = C_Sample_4clk | C_12BIT; // Sample pulse width=4 adc clock, ADC select 12-bit conversion ( Note: ADC clock freq. must be equal or less 1.25MHz)
ADCR = C_Sample_8clk | C_12BIT; // Sample pulse width=8 adc clock, ADC select 12-bit conversion ( Note: ADC clock freq. must be equal or less 2MHz)
//--------------------------------------------------
// Set AIN0(PA0) to AIN7(PB2) as pure ADC input for reduce power consumption (SFR "PACON")
PACON = C_PB0_AIN5 | C_PA1_AIN1; // C_PB2_AIN7 | C_PB1_AIN6 | C_PB0_AIN5 | C_PA4_AIN4 | C_PA3_AIN3 | C_PA2_AIN2 | C_PA1_AIN1 | C_PA0_AIN0;
// Set AIN8(PB3) as pure ADC input for reduce power consumption (SFR "ADCR")
ADCR |= C_Sample_8clk | C_12BIT | C_PB3_AIN8; // C_PB3_AIN8 |
ADMDbits.GCHS = 1; // Enable global ADC channel (SFR "ADMD")
delay(50); // Delay 0.56ms(Instruction clock=4MHz/2T) waiting ADC stable
}
ADC采集函数
ADMD寄存器
如果采集VDD的话电压要除于4
ch是采集通道
vref是参考电压:C_Vrefh_VDD,C_Vrefh_4V,C_Vrefh_3V,C_Vrefh_2V
unsigned int Get_ADC_Value(unsigned char ch, unsigned char vref) //,unsigned char vref)
{
unsigned char i = 3;
unsigned int value = 0, buf, max = 0, min = 0xFFFF;
ADMD = C_ADC_En | C_ADC_CH_Dis | C_Quarter_VDD;
ADMD = 0x90 | ch;
ADVREFH = vref;
delay(100);
while (i)
{
i--;
ADMDbits.START = 1; // Start a ADC conversion session
while (ADMDbits.EOC == 0)
; // Wait for ADC conversion complete
}
value = 0;
for (i = 0; i < 6; i++)
{
ADMDbits.START = 1; // Start a ADC conversion session
while (ADMDbits.EOC == 0)
; // Wait for ADC conversion complete
buf = ADD;
buf <<= 4;
buf |= 0x0F & ADR;
if (max <= buf)
max = buf;
if (min >= buf)
min = buf;
value += buf;
}
value -= max;
value -= min;
value >>= 2;
return value;
}
PWM初始化
引脚对应的pwm几就打开几
我只打开了pwm1和pwm5
void PWM_Init(void)
{
// Initial Timer 1 & PWM1/2 control register
TMRH = 0; // C_TMR1_Data_b9 | C_TMR1_Data_b8 | C_PWM2_Duty_b9 | C_PWM2_Duty_b8 ;
// TM4RH = 0; // C_TMR4_Data_b9 | C_TMR4_Data_b8 | C_PWM3_Duty_b9 | C_PWM3_Duty_b8;
TM5RH = 0; // C_TMR5_Data_b9 | C_TMR5_Data_b8 | C_PWM5_Duty_b8;
TMR1 = 0xFF; // Move FFH to TMR1 LB register ( TMR1[9:0]=3FFH )
// TMR4 = 0xFF; // Move FFH to TMR4 LB register ( TMR1[9:0]=3FFH )
TMR5 = 0xFF; // Move FFH to TMR5 LB register ( TMR1[9:0]=3FFH )
PWM1DUTY = 0; // Move 01H to PWM1DUTY LB register ( PWM1DUTY[9:0]=001H )
// PWM2DUTY = 0; // Move FFH to PWM2DUTY LB register ( PWM2DUTY[9:0]=3FFH )
// PWM3DUTY = 0; // Move FFH to PWM3DUTY LB register ( PWM3DUTY[9:0]=300H )
// PWM4DUTY = 0; // Move FFH to PWM4DUTY LB register ( PWM4DUTY[9:0]=0FFH )
PWM5DUTY = 0; // Move FFH to PWM5DUTY LB register ( PWM3DUTY[9:0]=100H )
T1CR2 = C_PS1_Dis | C_TMR1_ClkSrc_Inst; // Prescaler 1:1 , Timer1 clock source is instruction clock
T1CR1 = C_PWM1_En | C_PWM1_Active_Hi | C_TMR1_Reload | C_TMR1_En; // Enable PWM1 , Active_High , Non-Stop mode ,reloaded from TMR1[9:0] , enable Timer1
// P2CR1 = C_PWM2_En | C_PWM2_Active_Hi;
// P3CR1 = C_PWM3_En | C_PWM3_Active_Hi; // Enable PWM3 , Active_High , Non-Stop mode ,reloaded from TMR3[9:0] , enable Timer3
// T4CR2 = C_PS4_Dis | C_TMR4_ClkSrc_Inst; // Prescaler 1:1 , Timer4 clock source is instruction clock
// T4CR1 = C_PWM4_En | C_PWM4_Active_Hi | C_TMR4_Reload | C_TMR4_En; // Enable PWM4 , Active_High , Non-Stop mode ,reloaded from TMR4[9:0] , enable Timer4
T5CR2 = C_PS5_Dis | C_TMR5_ClkSrc_Inst; // Prescaler 1:1 , Timer5 clock source is instruction clock
T5CR1 = C_PWM5_En | C_PWM5_Active_Hi | C_TMR5_Reload | C_TMR5_En; // Enable PWM5 , Active_High , Non-Stop mode ,reloaded from TMR5[9:0] , enable Timer5
}
结构体写bit节省空间
8个标志位只占了1个字节
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
// union
//{
typedef struct
{
unsigned bit0 : 1;
unsigned bit1 : 1;
unsigned bit2 : 1;
unsigned bit3 : 1;
unsigned bit4 : 1;
unsigned bit5 : 1;
unsigned bit6 : 1;
unsigned bit7 : 1;
} byte;
byte flag_byte = {0}, flag_byte1 = {0};
#define time_10ms_flag flag_byte.bit0
#define power_flag flag_byte.bit1 // 开关机
#define direction_flag flag_byte.bit2 // 电机正反转 0正1反
#define volFull_flag flag_byte.bit3 // 充满
#define heat_mode_count flag_byte.bit4 // 0关闭 1高档
#define vbat_low_off_flag flag_byte.bit5 // 低电量
#define breath_flag flag_byte.bit6 // 呼吸灯
#define key_sign flag_byte.bit7
软推pwm实现呼吸灯
把该函数放中断执行就可以了
一旦打开breath_flag呼吸灯开始执行
//***************************呼吸灯程序******************************
void breath_led_func()
{
static u16 pwm_count = 0;
static u16 pwm_set = 0;
static u8 pwm_dir = 1;
static u8 pwm_set_count = 0;
if (breath_flag)
{
pwm_count++;
if (pwm_count < pwm_set)
LED_GREEN = 1;
else
LED_GREEN = 0;
if (pwm_count == 20) // 20*50us=1ms,pwm波频率为 1KHz
{
pwm_count = 0;
pwm_set_count++;
}
if (pwm_set_count == 50) // 50ms调整一次占空比,占空比调整频率为20Hz
{
pwm_set_count = 0;
if (pwm_dir == 1)
pwm_set++;
else
pwm_set--;
if (pwm_set == 20) // 20*500*2ms=2s为一个呼吸周期
pwm_dir = 0;
if (pwm_set == 0)
pwm_dir = 1;
}
}
else
{
pwm_count = 0;
}
}
ADC计算电压方法
电压V = (ad值/(2^adc位数))*参考电压