⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main887.c

📁 用PIC16F887做的4个触摸按键的例程
💻 C
📖 第 1 页 / 共 2 页
字号:

	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 + -