📄 main887.c
字号:
TMR1L = 0; // reset Timer1
TMR1H = 0; // " "
TMR1ON = 1; // restart Timer1
TMR0 = 0; // reset Timer0
T0IF = 0; // clear the interrupt
}
/*....................................................................
. CapInit()
.
. Performs Initializations for capacitive sensing.
....................................................................*/
void CapInit(void) {
// Load defaults for buttons
for (INDEX=0; INDEX < NUM_BTTNS; INDEX++) { // Load Default GB/TRP
if (INDEX != 0 && INDEX < 11) {
// Normal Buttons
RAW[INDEX] = 0;
AVERAGE[INDEX] = 0;
GUARD[INDEX] = 60;
TRIP[INDEX] = 145;
// Weaker sensors (make them a little more sensitive)
if (INDEX == i2)
TRIP[INDEX] = 120;
else if (INDEX == i3)
TRIP[INDEX] = 135;
else if (INDEX == i5)
TRIP[INDEX] = 120;
// Too strong sensors
if (INDEX == i0)
TRIP[INDEX] = 165;
} else if (INDEX != 0) {
// Specifically Tailored Sliders
if (INDEX == 11)
TRIP[INDEX] = 110; // Slider 1 is too insensitive, adjust to be more
if (INDEX == 12)
TRIP[INDEX] = 100; // Slider 2 is far too insensitive,
if (INDEX == 13)
TRIP[INDEX] = 110; // Slider 3 is too insensitive, adjust to be more
if (INDEX == 14)
TRIP[INDEX] = 115;
if (INDEX == 15)
TRIP[INDEX] = 130;
if (INDEX == 16)
TRIP[INDEX] = 130; // Slider 6 is a little insensitive, and should be semi-dominant on 'down swipes'
} else {
// Power button index
TRIP[INDEX] = 1500;
}
}
FIRST = 160; // first pass flag to reach steady state average before enabling detection
// All TRIS Registers set up in INIT() Routine
// Capacitively this requires to set up C2OUT as o/p, and T1CKI=i/p, C12INx- pins used = analog i/p., C2+ pin = analog i/p
OSCCON = 0x7F; // (Optional) Set for 8MHz internal clock.
VRCON = 0x87; // setup the CVref for 2/3VDD
CM1CON0 = COMP1[0]; // preset the comparators for first channel (and set appropriate enable bits)
CM2CON0 = COMP2[0];
INDEX = 0; // Init to start on button 0. { INDEX =button state machine state variable }
CM2CON1 = 0x32;
ANSEL = 0x07; // configure the button inputs for analog, along with the 1/4VDD reference input
ANSELH = 0x00;
SRCON = 0xF0; // turn on the SR flip flop mode
T1CON = 0x06; // enable timer1
OPTION = 0x84; // setup the timer0 prescaler
RestartTimers(); // Turn on and start timers
INTCON = 0; // clear the interrupt register
T0IE = 1; // turn on the timer0 interrupt
}
/*....................................................................
. CapISR(void)
.
. Capacitive service routine for ISR. This function should be
. called on each overflow of Timer0 which indicates a measurement
. is ready to be taken.
.
. It takes the measurement, determines if the button under test
. is pressed or not (setting a flag accordingly), and it then will
. average the new reading appropriately and then set the comparators
. to scan the next button in sequence.
....................................................................*/
void CapISR(void) {
// 1. Get the raw sensor reading.
// ...
VALUE = TMR1L + (unsigned int)(TMR1H << 8); // Get the frequency count for the current sensor
BIGVAL = VALUE * 16; // BIGVAL is current measurement left shifted 4 bits
SMALLAVG = AVERAGE[INDEX] / 16; // SMALLAVG is the current average right shifted 4 bits
RAW[INDEX] = BIGVAL; // RAW array holds the most recent BIGVAL values
// 2. On power-up, reach steady-state readings
// ...
// During power-up, system must be initialized, set average ea. pass
if (FIRST > 0) {
FIRST--; // Decr. N # times to establish startup
AVERAGE[INDEX] = BIGVAL; // During start up time, set Average each pass.
if (!Flags.SLEEP)
SetNextChannel();
RestartTimers(); // Restart the timers
return; // .. and exit
}
// 3. Is a keypad button pressed?
// ...
if (BIGVAL < (AVERAGE[INDEX] - TRIP[INDEX])) {
// Allow only 1 button pressed down at a time
if (!(Buttons.BTN0 || Buttons.BTN1 || Buttons.BTN2 ||
Buttons.BTN3 || Buttons.BTN4 || Buttons.BTN5 ||
Buttons.BTN6 || Buttons.BTN7 || Buttons.BTN8 || Buttons.BTN9)) {
switch(INDEX) {
case i0: Buttons.BTN0 = 1; Flags.BUZZDONE = 0; break; // Keypad 0(#10), 1-9 = Index 1-10
case i1: Buttons.BTN1 = 1; Flags.BUZZDONE = 0; break;
case i2: Buttons.BTN2 = 1; Flags.BUZZDONE = 0; break; // Clear Buzzdone whenever a new button
case i3: Buttons.BTN3 = 1; Flags.BUZZDONE = 0; break; // press is detected to allow
case i4: Buttons.BTN4 = 1; Flags.BUZZDONE = 0; break; // buzzer logic to make a beep.
case i5: Buttons.BTN5 = 1; Flags.BUZZDONE = 0; break;
case i6: Buttons.BTN6 = 1; Flags.BUZZDONE = 0; break;
case i7: Buttons.BTN7 = 1; Flags.BUZZDONE = 0; break;
case i8: Buttons.BTN8 = 1; Flags.BUZZDONE = 0; break;
case i9: Buttons.BTN9 = 1; Flags.BUZZDONE = 0; break;
}
}
}
// 3b. Power button pressed?
// ...
if (INDEX == iPWR && (BIGVAL < (AVERAGE[INDEX] - TRIP[INDEX])) ) {
Buttons.PWR = 1;
}
// 4. Is a slider button pressed?
// ...
if ( (BIGVAL < (AVERAGE[INDEX] - TRIP[INDEX])) ) {
// Is BIGVAL below { AVERAGE - TRIP } ? .. Yes
// Button is down.
// Set flag for button that is pressed.
switch(INDEX) {
case iSL1: Buttons.SLIDER1 = 1; // Slider 1-6 = Index 11-16
Buttons.SLIDER2 = 0;
Buttons.SLIDER3 = 0;
Buttons.SLIDER4 = 0;
Buttons.SLIDER5 = 0;
Buttons.SLIDER6 = 0;
SliderIndex = 1;
break;
case iSL2: Buttons.SLIDER1 = 0;
Buttons.SLIDER2 = 1;
Buttons.SLIDER3 = 0;
Buttons.SLIDER4 = 0;
Buttons.SLIDER5 = 0;
Buttons.SLIDER6 = 0;
SliderIndex = 2; // Will set LEDs, pulling down oscillator freq,
break; // but will do so before averages of buttons below
case iSL3: Buttons.SLIDER1 = 0; // can respond. Setting the SliderIndex value
Buttons.SLIDER2 = 0;
Buttons.SLIDER3 = 1;
Buttons.SLIDER4 = 0;
Buttons.SLIDER5 = 0;
Buttons.SLIDER6 = 0;
SliderIndex = 3; // Shows the highest level of on value, and will
break; // allow averaging to be done on buttons beneath it
case iSL4: Buttons.SLIDER1 = 0; // so that they do not become stuck.
Buttons.SLIDER2 = 0;
Buttons.SLIDER3 = 0;
Buttons.SLIDER4 = 1;
Buttons.SLIDER5 = 0;
Buttons.SLIDER6 = 0;
SliderIndex = 4;
break;
case iSL5: Buttons.SLIDER1 = 0;
Buttons.SLIDER2 = 0;
Buttons.SLIDER3 = 0;
Buttons.SLIDER4 = 0;
Buttons.SLIDER5 = 1;
Buttons.SLIDER6 = 0;
SliderIndex = 5;
break;
case iSL6: Buttons.SLIDER1 = 0;
Buttons.SLIDER2 = 0;
Buttons.SLIDER3 = 0;
Buttons.SLIDER4 = 0;
Buttons.SLIDER5 = 0;
Buttons.SLIDER6 = 1;
SliderIndex = 6;
break;
default: break;
}
}
// 5. Is a button unpressed?
// ...
if (BIGVAL > (AVERAGE[INDEX] - TRIP[INDEX] + 32)) {
// Is BIGVAL above { average - (trip + hysteresis) } ? .. Yes
// Button is up.
switch(INDEX) {
case i0: Buttons.BTN0 = 0; break;
case i1: Buttons.BTN1 = 0; break;
case i2: Buttons.BTN2 = 0; break;
case i3: Buttons.BTN3 = 0; break;
case i4: Buttons.BTN4 = 0; break;
case i5: Buttons.BTN5 = 0; break;
case i6: Buttons.BTN6 = 0; break;
case i7: Buttons.BTN7 = 0; break;
case i8: Buttons.BTN8 = 0; break;
case i9: Buttons.BTN9 = 0; break;
case iSL1: Buttons.SLIDER1 = 0; break;
case iSL2: Buttons.SLIDER2 = 0; break;
case iSL3: Buttons.SLIDER3 = 0; break;
case iSL4: Buttons.SLIDER4 = 0; break;
case iSL5: Buttons.SLIDER5 = 0; break;
case iSL6: Buttons.SLIDER6 = 0; break;
case iPWR: Buttons.PWR = 0; break;
default: break;
}
}
// 6. Implement quick-release for a released button
// ...
if (BIGVAL > AVERAGE[INDEX]) {
AVERAGE[INDEX] = AVERAGE[INDEX] + (VALUE - SMALLAVG); // Average in higher value every pass (not on timed delays), averaging protects against large spikes.
}
// 7. Average in the new value
// ...
// Always Average (all buttons)
if (AvgIndex < AVG_DELAY) AvgIndex++; // Counting 0..8 has effect of every 9th count cycling the next button.
else AvgIndex = 0; // Counting 0..4 will average faster and also can use 0..4*m, m=0,1,2,3..
if (AvgIndex == AVG_DELAY) {
// Average in raw value.
AVERAGE[INDEX] = AVERAGE[INDEX] + (VALUE - SMALLAVG);
}
// Determine next sensor to test.
if (!Flags.SLEEP) // Don't change channels during sleep
SetNextChannel();
// Restart timers for next pass
RestartTimers();
}
/*....................................................................
. SetNextChannel()
.
. The SetNextChannel function will set the next channel in
. sequence to be scanned based off of the current index value.
....................................................................*/
void SetNextChannel(void) {
// 8. Complete code to change channels
// ...
// Determine next sensor to test.
if ( INDEX <= (NUM_BTTNS - 1) ) { // if (less than total index maximum) ..
INDEX++; // Incr. to test next button if not last index value
MUXSEL = (INDEX <= 8) ? 1 : 0; // (if:else)
CTL_PORT &= 0xF8; // Clear Low 3 bits
CTL_PORT |= ( ( (INDEX-1) % 8) & 0x07 ); // Set 3 LSb's properly for MUXes.
} else {
INDEX = 0; /// Wrap around if just tested the last button
MUXSEL = 1; // Reset MUXSEL
CTL_PORT = CTL_PORT & 0xF8; // Reset S<2:0>
}
// Configure comparators for the new sensor
if (INDEX == 0) {
CM1CON0 = COMP1[0]; // Power button, Index 0 is on CIN0-
CM2CON0 = COMP2[0];
} else {
CM1CON0 = COMP1[1]; // All others (MUXes), are on CIN1-
CM2CON0 = COMP2[1];
}
}
/*....................................................................
. SetChannel()
.
. The SetChannel function will set the next channel in
. sequence to be scanned based off of the supplied index value.
. It assumes a valid index value.
....................................................................*/
void SetChannel(char idx) {
INDEX = idx; // Set state variable index.
// Configure muxes as needed
MUXSEL = (INDEX <= 8) ? 1 : 0; // (if:else)
CTL_PORT &= 0xF8; // Clear Low 3 bits
CTL_PORT |= ( ( (INDEX-1) % 8) & 0x07 ); // Set 3 LSb's properly for MUXes.
// Configure comparators for the new sensor
if (INDEX == 0) {
CM1CON0 = COMP1[0]; // Power button, Index 0 is on CIN0-
CM2CON0 = COMP2[0];
} else {
CM1CON0 = COMP1[1]; // All others (MUXes), are on CIN1-
CM2CON0 = COMP2[1];
}
}
/*....................................................................
. ShutdownWheel()
.
. Issues I2C command to 16F677 on SDA and SCL lines to put it
. in sleep.
....................................................................*/
void ShutdownWheel(void) {
// Must send the following command to the 16F677 to shut it down
// [S] DAw CommandByte DummyByte DummyByte [P]
SSPIE = 0; // For simple cmd, avoid req'ng use of intpts
SEN = 1; // Issue start bit
while (SEN); // wait for start bit completion
SSPBUF = _16F677_DEVICEADDR; // Send 677 DA with write bit
while (RW); // Wait while transmission in progress
SSPBUF = _16F677_SHUTDOWN; // Issue shutdown cmd
while (RW); // Wait while transmission in progress
SSPBUF = 0x00; // Send 0x00 to comply with formatting
while (RW); // Wait while transmission in progress
SSPBUF = 0X00; // Send 0x00 to comply with formatting
while (RW); // Wait while transmission in progress
PEN = 1; // Issue stop bit
while (PEN); // Wait for completion, EOT
SSPIE = 1; // Re-enable intpts for GUI communication
}
/*....................................................................
. WakeupWheel()
.
. Issues I2C command to 16F677 on SDA and SCL lines to wake it
. from sleep.
....................................................................*/
void WakeupWheel(void) {
// Must send the following command to the 16F677 to shut it down
// [S] DAw CommandByte DummyByte DummyByte [P]
SSPIE = 0; // For simple cmd, avoid req'ng use of intpts
SEN = 1; // Issue start bit
while (SEN); // wait for start bit completion
SSPBUF = _16F677_DEVICEADDR; // Send 677 DA with write bit
while (RW); // Wait while transmission in progress
SSPBUF = _16F677_WAKEUP; // Issue wakeup command
while (RW); // Wait while transmission in progress
SSPBUF = 0x00; // Send 0x00 to comply with formatting
while (RW); // Wait while transmission in progress
SSPBUF = 0x00; // Send 0x00 to comply with formatting
while (RW); // Wait while transmission in progress
PEN = 1; // Issue stop bit
while (PEN); // Wait for completion, EOT
SSPIE = 1; // Re-enable intpts for GUI communication
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -