如果开发环境不支持bit 定义static unsigned char task_720ms_flag = 0;还可以用什么方式替代bit定义标志,使其占用内存空间小。
如果开发环境不支持位定义,可以使用 unsigned char
的多个状态位来替代。可以将多个标志合并到一个 unsigned char
中,每个标志使用一个特定位。例如:
static unsigned char task_flags = 0; // 使用一个字节来存储多个标志// 定义标志位
#define TASK_5MS_FLAG (1 << 0)
#define TASK_10MS_FLAG (1 << 1)
#define TASK_30MS_FLAG (1 << 2)
#define TASK_50MS_FLAG (1 << 3)
#define TASK_100MS_FLAG (1 << 4)
#define TASK_720MS_FLAG (1 << 5)// 设置标志
task_flags |= TASK_720MS_FLAG;// 清除标志
task_flags &= ~TASK_720MS_FLAG;// 检查标志
if (task_flags & TASK_720MS_FLAG) {// 标志已设置
}
这样可以在一个字节中存储多个标志,节省内存空间。
task_flags |= TASK_720MS_FLAG;
这个操作会将 TASK_720MS_FLAG
对应的位设置为1,而不改变其他位的值。因此,如果 task_flags
最开始是0,经过这条语句后,TASK_720MS_FLAG
所对应的位将变为1,其他位保持不变。
例如,如果 TASK_720MS_FLAG
定义为 0x20
(即二进制的 0010 0000
),那么:
- 初始值
task_flags = 0x00
(所有位为0) - 执行后
task_flags = 0x20
(第6位变为1)
如果 task_flags
已经有其他位为1,|=
操作会将对应的位设置为1,而保留其他位的状态。
/* =========================================================================* Project: Timer Interrupt & WDT Interrupt* File: main.c* Description: Set Timer0、Timer1、WDT Interrupt* 1. FINST = 4MHz/4T(I_HRC)* 2. Timer0 overflow interrupt flag bit will be set every 2048us then toggle PB0 output state (2048us = 1us*256*8)* 3. Timer1 underflow interrupt flag bit will be set every 1024us then toggle PB1 output state (1024us = 1us*256*4)* 4. WDT timeout interrupt flag bit will be set every 3.5ms then toggle PB2 output state* 4.1 Set project options : WDT Time Base = 3.5ms** Author: JasonLee* Version: V1.0* Date: 2017/11/08=========================================================================*/#include <ny8.h>
#include "ny8_constant.h"
#define UPDATE_REG(x) __asm__("MOVR _" #x ",F")//PB0 -- 转灯
//PB1 -- 位置灯
//PB2 -- 转灯信号#define TURN_LIGHT_O PB0
#define POSIT_LIGHT_O PB1
#define TURN_SINGLE_I PB2static unsigned long low_time = 0; // 用于记录低电平持续时间
static unsigned char task_flags = 0;#define task_5ms_flag (1 << 0)
#define task_10ms_flag (1 << 1)
#define task_30ms_flag (1 << 2)
#define task_50ms_flag (1 << 3)
#define task_100ms_flag (1 << 4)
#define task_720ms_flag (1 << 5)
#define Left_Turn_Flag (1 << 6)void Single_Scan(void) {//static unsigned long low_time = 0; // 用于记录低电平持续时间if (PORTBbits.PB2 == 0) { // 检测到低电平if (low_time < 1000) {low_time++; // 增加计时}// delay_ms(2); // 2ms 延时if ((TURN_SINGLE_I == 0) && (low_time >= 500)) { // 超过 1s 且 LED 关闭// Left_Turn_Flag = 0;task_flags &= ~Left_Turn_Flag;TURN_LIGHT_O = 0;POSIT_LIGHT_O = 1;}} else { // 检测到高电平low_time = 0; // 重置计时task_flags |= Left_Turn_Flag;// Left_Turn_Flag = 1;POSIT_LIGHT_O = 0;}
}//! interrupt service routine
void isr(void) __interrupt(0) {static unsigned char count_5ms = 0;static unsigned char count_10ms = 0;static unsigned char count_100ms = 0;static unsigned char count_720ms = 0;if(INTFbits.T1IF) {count_5ms++;if (count_5ms >= 5) {count_5ms = 0;// task_5ms_flag = 1;task_flags |= task_5ms_flag;}// 100ms任务count_100ms++;if (count_100ms >= 100) {count_720ms++;count_100ms = 0;// task_100ms_flag = 1;task_flags |= task_100ms_flag;if(count_720ms >= 144) {count_720ms = 0;// task_720ms_flag = 1;task_flags |= task_720ms_flag;}}// 50ms任务if (count_100ms % 50 == 0) {// task_50ms_flag = 1;task_flags |= task_50ms_flag;}// 30ms任务if (count_100ms % 30 == 0) {// task_30ms_flag = 1;task_flags |= task_30ms_flag;}// 10ms任务count_10ms++;if (count_10ms >= 10) {count_10ms = 0;// task_10ms_flag = 1;task_flags |= task_10ms_flag;}//PORTB ^= (1<<1); // PB1 ToggleINTF= (unsigned char)~(C_INT_TMR1); // Clear T1IF flag bit}if(INTFbits.T0IF) {Single_Scan();////PORTB ^= 1; // PB0 ToggleINTF= (unsigned char)~(C_INT_TMR0); // Clear T0IF flag bit}if(INTFbits.WDTIF) {//PORTB ^= (1<<2); // PB2 ToggleINTF= (unsigned char)~(C_INT_WDT); // Clear WDTIF flag bit}}void main(void) {unsigned char R_shift_regl = 0xFF;
//;Initial GPIOIOSTB = C_PB2_Input; // Set PB2 to input mode,others set to output mode//IOSTB = C_PB5_Input | C_PB4_Input | C_PB3_Input; // Set PB0 & PB1 to input mode,others set to output mode//PORTB = 0x07; // PB0、PB1 & PB2 are output HighPORTB = 0x00; // LOWDISI();
//;Initial Timer0PCON1 = C_TMR0_Dis; // Disable Timer0TMR0 = 0; // Load 0x00 to TMR0 (Initial Timer0 register)T0MD = C_PS0_TMR0 | C_PS0_Div8 ; // Prescaler0 is assigned to Timer0, Prescaler0 dividing rate = 1:8,clock source is instruction clock//;--Initial WDT (if WDT needs prescaler0 dividing rate )--------------------------------------------------
// T0MD = C_PS0_WDT // Prescaler0 is assigned to WDT, Prescaler0 dividing rate = 1:2 (WDT select interrupt)
//;--------------------------------------------------------------------------------------------------------//;Initial Timer1TMR1 = 0xFF; // Load 0xFF to TMR1 (Initial Timer1 register)T1CR1 = C_TMR1_Reload | C_TMR1_En; // Enable Timer1, Initial value reloaded from TMR1, Non-stop modeT1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Div4; // Enable Prescaler1, Prescaler1 dividing rate = 1:4, Timer1 clock source is instruction clock//;Setting Interrupt Enable RegisterINTE = C_INT_WDT | C_INT_TMR1 | C_INT_TMR0; // Enable Timer0、Timer1、WDT overflow interrupt//;Initial Power control registerPCON = C_WDT_En | C_LVR_En; // Enable WDT , Enable LVR//;Enable Timer0 & Global interrupt bitPCON1 = C_TMR0_En; // Enable Timer0ENI(); // Enable all unmasked interruptswhile(1) {if(task_flags & task_720ms_flag) {// task_720ms_flag = 0;task_flags &= ~task_720ms_flag;POSIT_LIGHT_O = 0;TURN_LIGHT_O = ~TURN_LIGHT_O;}if (task_flags & task_100ms_flag) {// task_100ms_flag = 0;task_flags &= ~task_100ms_flag;}if (task_flags & task_50ms_flag) {// task_50ms_flag = 0;task_flags &= ~task_50ms_flag;}if (task_flags & task_30ms_flag) {// task_30ms_flag = 0;task_flags &= ~task_30ms_flag;}if (task_flags & task_10ms_flag) {// task_10ms_flag = 0;task_flags &= ~task_10ms_flag;}if (task_flags & task_5ms_flag) {// task_5ms_flag = 0;task_flags &= ~task_5ms_flag;}}
}
/* =========================================================================* Project: Timer Interrupt & WDT Interrupt* File: main.c* Description: Set Timer0、Timer1、WDT Interrupt* 1. FINST = 4MHz/4T(I_HRC)* 2. Timer0 overflow interrupt flag bit will be set every 2048us then toggle PB0 output state (2048us = 1us*256*8)* 3. Timer1 underflow interrupt flag bit will be set every 1024us then toggle PB1 output state (1024us = 1us*256*4)* 4. WDT timeout interrupt flag bit will be set every 3.5ms then toggle PB2 output state* 4.1 Set project options : WDT Time Base = 3.5ms** Author: JasonLee* Version: V1.0* Date: 2017/11/08=========================================================================*/
#include <ny8.h>
#include "ny8_constant.h"
#define UPDATE_REG(x) __asm__("MOVR _" #x ",F")//PB0 -- 转灯
//PB1 -- 位置灯
//PB2 -- 转灯信号#define TURN_LIGHT_O PB0
#define POSIT_LIGHT_O PB1
#define TURN_SINGLE_I PB2static unsigned long low_time = 0; // 用于记录低电平持续时间
static unsigned char Left_Turn_Flag = 0;
static unsigned long count_720ms = 0;
static unsigned char task_720ms_flag = 0;void Single_Scan(void) {//static unsigned long low_time = 0; // 用于记录低电平持续时间if (PORTBbits.PB2 == 0) { // 检测到低电平if (low_time < 1000) {low_time++; // 增加计时}// delay_ms(2); // 2ms 延时if ((PORTBbits.PB2 == 0) && (low_time >= 500)) { // 超过 1s 且 LED 关闭Left_Turn_Flag = 0;//TURN_LIGHT_O = 0;//POSIT_LIGHT_O = 1;}} else { // 检测到高电平low_time = 0; // 重置计时Left_Turn_Flag = 1;//POSIT_LIGHT_O = 0;}
}//! interrupt service routine
void isr(void) __interrupt(0) {if(INTFbits.T1IF) {count_720ms++;if(count_720ms >= 720) {count_720ms = 0;task_720ms_flag = 1;}//PORTB ^= (1<<1); // PB1 ToggleINTF= (unsigned char)~(C_INT_TMR1); // Clear T1IF flag bit}if(INTFbits.T0IF) {Single_Scan();//PORTB ^= 1; // PB0 Toggle//TURN_LIGHT_O = PORTBbits.PB2;INTF= (unsigned char)~(C_INT_TMR0); // Clear T0IF flag bit}if(INTFbits.WDTIF) {//PORTB ^= (1<<2); // PB2 ToggleINTF= (unsigned char)~(C_INT_WDT); // Clear WDTIF flag bit}}void main(void) {unsigned char R_shift_regl = 0xFF;
//;Initial GPIO//IOSTB = C_PB5_Input | C_PB4_Input | C_PB3_Input; // Set PB0 & PB1 to input mode,others set to output mode//PORTB = 0x07; // PB0、PB1 & PB2 are output HighIOSTB = C_PB2_Input;PORTB = 0x00;DISI();
//;Initial Timer0PCON1 = C_TMR0_Dis; // Disable Timer0TMR0 = 0; // Load 0x00 to TMR0 (Initial Timer0 register)T0MD = C_PS0_TMR0 | C_PS0_Div8 ; // Prescaler0 is assigned to Timer0, Prescaler0 dividing rate = 1:8,clock source is instruction clock//;--Initial WDT (if WDT needs prescaler0 dividing rate )--------------------------------------------------
// T0MD = C_PS0_WDT // Prescaler0 is assigned to WDT, Prescaler0 dividing rate = 1:2 (WDT select interrupt)
//;--------------------------------------------------------------------------------------------------------//;Initial Timer1TMR1 = 0xFF; // Load 0xFF to TMR1 (Initial Timer1 register)T1CR1 = C_TMR1_Reload | C_TMR1_En; // Enable Timer1, Initial value reloaded from TMR1, Non-stop modeT1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Div4; // Enable Prescaler1, Prescaler1 dividing rate = 1:4, Timer1 clock source is instruction clock//;Setting Interrupt Enable RegisterINTE = C_INT_WDT | C_INT_TMR1 | C_INT_TMR0; // Enable Timer0、Timer1、WDT overflow interrupt//;Initial Power control registerPCON = C_WDT_En | C_LVR_En; // Enable WDT , Enable LVR//;Enable Timer0 & Global interrupt bitPCON1 = C_TMR0_En; // Enable Timer0ENI(); // Enable all unmasked interruptswhile(1) {if(task_720ms_flag) {task_720ms_flag = 0;if(Left_Turn_Flag) {POSIT_LIGHT_O = 0;//TURN_LIGHT_O = ~TURN_LIGHT_O;PORTB ^= 1;// PB0 Toggle} else {TURN_LIGHT_O = 0;POSIT_LIGHT_O = 1;}}}
}