Debounce button in PIC - c

I newbie in PIC mcu. I use pic12f675 MPLAB and XC8 for make an LED multiple blink pattern.
and I have problem with push button (after review it call Bounce and Debounce).
Sometime when I press button it will in sequence ex. 1->2->3->4->5 but sometime it will jump ex. 1->3->4->6 etc.
Please advice me How to debounce in pic mcu or another way to solve my problem.
Thank you. everyone.
(PS.I connect push button with 10K resistor)
my code at below
#include <xc.h>
#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
#define _XTAL_FREQ 4000000
int cnt = 0;
int k = 0;
void __interrupt() MyISR(void){
if(INTCONbits.INTF) //If External Edge INT Interrupt
{
cnt++;
INTCONbits.GIE = 0;
INTCONbits.INTF = 0; // Clear the interrupt
INTCONbits.GPIF = 0;
if( cnt > 6 ){
cnt = 1;
}
}
INTCONbits.GIE = 1;
}
void main(void) {
ANSEL = 0;
CMCON = 0b00000111; //turns comparators off
TRISIO = 0b00000100;
GPIO = 0;
TRISIO2 = 1; // Make GP2 pin as input
INTCONbits.GIE = 1;
INTCONbits.INTE = 1;
INTCONbits.GPIF = 1;
INTCONbits.INTF = 0;
OPTION_REG = 0b01000000;
while(1){
if( cnt == 1 ){
GP0 = 1;
GP5 = 1;
}else if( cnt == 2 ){
for(k=0;k<30;k++){
GP5 = 1;
GP0 = 1;
}
k=0;
while(k<3){
GP5 = ~GP5;
__delay_ms(70);
GP0 = ~GP0;
__delay_ms(70);
k++;
}
}else if( cnt == 3 ){
for(k=0;k<5;k++){
GP5 = 1;
GP0 = 1;
__delay_ms(70);
GP5 = 0;
GP0 = 0;
__delay_ms(70);
}
GP5 = 0;
GP0 = 0;
__delay_ms(1200);
}else if( cnt == 4 ){
for(k=0;k<3;k++){
GP0 = 1;
__delay_ms(50);
GP0 = 0;
__delay_ms(50);
}
for(k=0;k<3;k++){
GP5 = 1;
__delay_ms(50);
GP5 = 0;
__delay_ms(50);
}
}else if( cnt == 5 ){
GP0 = 1;
GP5 = 1;
for(k=0;k<3;k++){
GP5 = 1;
__delay_ms(50);
GP5 = 0;
__delay_ms(50);
}
GP0 = 1;
GP5 = 1;
for(k=0;k<3;k++){
GP0 = 1;
__delay_ms(50);
GP0 = 0;
__delay_ms(50);
}
}else if( cnt == 6 ){
GP0 = 1;
GP5 = 1;
__delay_ms(20);
GP0 = 0;
GP5 = 0;
__delay_ms(3000);
}
}
return;
}

I rewrite your code and tested it in MPLAB simulation. It works as expected. It changes modes in ascending order, then runs in the selected mode until the change button pressed again, then it changes to the next mode. You can add more working modes if you want or you can modify the way the how GPIOs blinking. There is no __delay_ms(), that's why the delays run without consuming the CPU. Please test it in a real circuit and give me a feedback.
/*
* File: main.c
* Author: kozmotronik
*
*/
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>
#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
// Work mode definitions
#define MODE_IDLE 0
#define MODE_OFF 1
#define MODE_ON 2
#define MODE_SLOW 3
#define MODE_FAST 4
#define MODE_CANCEL 5
#define LAST_MODE MODE_FAST
// Button states
#define BUTTON_IDLE 0
#define BUTTON_PRESS_DETECTED 1
#define BUTTON_DEBOUNCING 2
#define BUTTON_PRESS_CONFIRMED 3
#define SYSTEM_CLOCK_MS 1
#define SYSTEM_CLOCK_uS (SYSTEM_CLOCK_MS * 1000)
#define _XTAL_FREQ_MHZ (_XTAL_FREQ / 1000000) // Oscillator freq in MHz
#define TMR0_RELOAD_VALUE 256 - ( (SYSTEM_CLOCK_uS * _XTAL_FREQ_MHZ) / (8 * 4) ) // Result must be 131
#define MS_TO_TICKS(msTime) (msTime / SYSTEM_CLOCK_MS)
typedef struct{
unsigned int start;
unsigned int ticks;
} time_t;
char mode = MODE_IDLE;
char lastMode = MODE_OFF;
char buttonState = BUTTON_IDLE;
char k = 0;
unsigned int systemTick = 0; // Time value count by Timer0
void __interrupt() MyISR(void){
if(INTCONbits.INTF) //If External Edge INT Interrupt
{
INTCONbits.INTF = 0; // Clear the interrupt
buttonState = BUTTON_PRESS_DETECTED; // Signal the detected press
}
// Check for 1 ms periodic interrupt for system clock
else if(INTCONbits.T0IF){
INTCONbits.T0IF = 0; // clear flag
TMR0 = TMR0_RELOAD_VALUE; // Reload the calculated value for 1 ms
systemTick++;
}
}
// Setup Timer0 for 1ms interrupt
void setupTimer0(){
#define PRESCALER_VALUE 2
#define PRESCALER_MASK ~7
OPTION_REG &= PRESCALER_MASK; // Clear prescaler bits
OPTION_REG |= PRESCALER_VALUE; // Set prescaler value for 1:8
OPTION_REGbits.PSA = 0; // Assign prescaler to Tim0
OPTION_REGbits.T0CS = 0; // Set internal oscillator as clock source
TMR0 = TMR0_RELOAD_VALUE;
INTCONbits.T0IF = 0;
INTCONbits.T0IE = 1; // Enable Timer0 interrupt
}
// Get count atomically
unsigned int getTickCount(){
unsigned int count;
di(); // disable interrupts
count = systemTick;
ei(); // enable interrupts again
return count;
}
void performMode(){
static time_t modeDelay;
static char slowModeState = 1;
static char fastModeState = 1;
switch(mode){
case MODE_OFF:
// Always must save the current mode before put it into the IDLE
lastMode = mode; // We have to save the last mode first then put it into the IDLE state
mode = MODE_IDLE; // The rollover bug caused by here since we haven't save the last mode before put it into the IDLE state
GP0 = 0; GP5 = 0;
break;
case MODE_ON:
GP0 = 1; GP5 = 1;
break;
case MODE_SLOW:
if(slowModeState == 1){
GP0 = 1; GP5 = 1;
modeDelay.ticks = MS_TO_TICKS(100);
modeDelay.start = getTickCount();
slowModeState = 2; // Proceed the next step
}
else if(slowModeState == 2){
if( !((getTickCount() - modeDelay.start) >= modeDelay.ticks) ){
// Delay not expired yet
return;
}
GP0 = ~GP0; GP5 = ~GP5; // Toggle
// Reload the start time
modeDelay.start = getTickCount();
}
break;
case MODE_FAST:
if(fastModeState == 1){
GP0 = 1; GP5 = 1;
modeDelay.ticks = MS_TO_TICKS(50);
modeDelay.start = getTickCount();
fastModeState = 2; // Proceed the next step
}
else if(fastModeState == 2){
if( !((getTickCount() - modeDelay.start) >= modeDelay.ticks) ){
// Delay not expired yet
return;
}
// Delay time expired, proceed toggle
GP0 = ~GP0; GP5 = ~GP5; // Toggle
// Reload the start time
modeDelay.start = getTickCount();
}
break;
case MODE_CANCEL:
// Cancel the current running mode, reset everything
modeDelay.start = 0;
modeDelay.ticks = 0;
slowModeState = 1;
fastModeState = 1;
// Also reset the outputs
GP0 = 0; GP5 = 0;
break;
default:
mode = MODE_IDLE;
}
}
void checkButton(){
#define DEBOUNCE_DELAY_MS 100u // Debounce delay is 100 ms
static time_t debounceTimer;
switch(buttonState){
case BUTTON_IDLE:
break;
case BUTTON_PRESS_DETECTED:
debounceTimer.ticks = MS_TO_TICKS(DEBOUNCE_DELAY_MS);
debounceTimer.start = getTickCount();
buttonState = BUTTON_DEBOUNCING;
break;
case BUTTON_DEBOUNCING:
if( !((getTickCount() - debounceTimer.start) >= debounceTimer.ticks) ){
// Debounce time has not expired yet
return;
}
// Debounce time has expired so check the button last time to confirm if it is still pressed
if(GPIObits.GP2 != 1){
// Not stable yet, debounce again
buttonState = BUTTON_PRESS_DETECTED;
}
// Button press is stable, confirm it
buttonState = BUTTON_PRESS_CONFIRMED;
break;
case BUTTON_PRESS_CONFIRMED:
buttonState = BUTTON_IDLE; // Change state so that it can process a new button press
if(mode != MODE_IDLE && mode != MODE_OFF){
// Cancel the running mode first
lastMode = mode; // save the last mode
mode = MODE_CANCEL; // purge the current one
performMode();
}
mode = lastMode + 1; // Switch to next mode
if(mode > LAST_MODE){
// Rewind mode to the beginning which is MODE_OFF
mode = MODE_OFF;
}
break;
default:
buttonState = BUTTON_IDLE;
}
}
void main(void) {
ANSEL = 0;
CMCON = 0b00000111; //turns comparators off
TRISIO = 0b00000100;
GPIO = 0;
TRISIO2 = 1; // Make GP2 pin as input
INTCONbits.INTF = 0;
INTCONbits.INTE = 1;
INTCONbits.GIE = 1;
OPTION_REG = 0b01000000; // Rising edge interrupt
setupTimer0();
// Super loop
while(1){
// Task 1: Button check
if(buttonState != BUTTON_IDLE){
checkButton();
}
// Task 2: Mode check
else if(mode != MODE_IDLE){
performMode();
}
}
return;
}

Related

Programming of built in timer of arduino

I am new to programming in IDE. I am using built-in timer of arduino.I am using TDR method to capture reflection from fault location in cable and for that I am using timer.Timer should start as soon as output is send and stop at reflection. I have a reference code for it but I dont able to understand it, so if anyone know about it , it would be great.
void setup()
{
pinMode(stepPin, OUTPUT);
pinMode(refPin, OUTPUT);
pinMode(shutdownPin, OUTPUT);
TCCR1A = 0;
TCCR1B = (1 << ICNC1); // input capture noise canceller enabled, capture on falling edge
TIMSK1 = 0; // timer 1 interrupts disabled
ACSR = 0; // input capture from ICP1 pin
TCCR2B = (1 << CS20); // change timer 2 PWM frequency to 31.25kHz because we're using pin 11 as a DAC
Serial.begin(19200);
}
struct Step
{
unsigned int time;
unsigned int amplitude;
};
// Take a single measurement, using either a positive or negative edge from the comparator.
// The comparator reference voltage must have been set up and allowed to stablise before calling this.
unsigned int takeMeasurement(bool posEdge)
{
byte reg1b = (posEdge) ? 0 : (1 << ICES1); // input capture noise canceller csdisabled, set up input capture polarity, stop timer
reg1b |= (1 << CS10);
TCCR1B = reg1b;
TCNT1H = 0;
TCNT1L = 0; // clear timer
unsigned int capture = 0;
unsigned long start = micros(); // get the time
cli();
TCNT1H = 0;
TCNT1L = 0; // clear timer
TIFR1 = (1 << ICF1); // clear timer 1 input capture bit
PORTD |= (1 << 4); // set output high
sei();
do
{
if ((TIFR1 & (1 << ICF1)) && capture == 0)
{
byte temp = ICR1L;
capture = (ICR1H << 8) | temp;
}
} while (micros() - start < 100);
PORTD &= ~(1 << 4); // set output low
return capture;
}
size_t findSteps(bool positive, struct Step *results, size_t maxResults)
{
byte amplitude = (positive) ? 5 : 250;
analogWrite(refPin, amplitude);
delay(100); // wait 100ms for the output to stabilise
unsigned int lastReading = 0;
size_t numResults = 0;
unsigned int stepSize = 0; // 0 means not in a step
#ifdef DEBUG
Serial.print((positive) ? "pos " : "neg ");
#endif
for (int i = 0; i < 50; ++i)
{
analogWrite(refPin, amplitude);
delay(10);
unsigned int currentReading = takeMeasurement(positive);
unsigned int currentDiff = currentReading - lastReading; // diff since start of possible step
if (stepSize == 0)
{
// Not currently in a step
if (i != 0 && currentReading != 0 && currentDiff == 0)
{
// Found the start of a possible step
++stepSize;
}
lastReading = currentReading;
}
else
{
if (currentDiff > 2 || i + 1 == 50)
{
// Step has endeed, so record it if it is big enough
if (stepSize >= 2)
{
results->time = lastReading;
results->amplitude = amplitude - 5;
++results;
++numResults;
if (numResults == maxResults) break;
}
stepSize = 0;
lastReading = currentReading;
}
else if (currentDiff == 0)
{
++stepSize;
}
}
#ifdef DEBUG
if (i != 0) Serial.write(',');
Serial.print(currentReading);
#endif
if (positive)
{
amplitude += 5;
}
else
{
amplitude -= 5;
}
}
#ifdef DEBUG
Serial.println();
#endif
return numResults;
}

Design for a C Program Using Timer2 Interrupts

I'm programming my C code onto a PIC board. My question is how to get my program to count how long a button (RB0) is pressed down. It then displays the time it took and display it on an LCD Display. It counts in ms. Below is my code so far.
// Global Variables
unsigned int COUNTER;
// Subroutine Declarations
#include <pic18.h>
#include "lcd_portd.c"
//LCD routine, modified from previous examples
void LCD_Out(unsigned int STUFF, unsigned char A)
{
unsigned char C[5], i;
for (i=0; i<5; i++)
{
C[i] = STUFF % 10;
STUFF = STUFF / 10;
}
for (i=5; i>0; i--)
{
if (i == A) LCD_Write('.');
LCD_Write(C[i-1] + '0');
}
}
void interrupt IntServe(void)
{
if (TMR2IF)
{
RB0 = !RB0;
TMR2IF = 0;
COUNTER = COUNTER + 1;
}
}
// Main Routine
void main(void)
{
//Instantiate all Ports to ready for Timers and pin sets
LCD_Init();
TRISA = 0;
TRISB = 0;
TRISC = 0;
TRISD = 0;
TRISE = 0;
ADCON1 = 0x0F;
//Timer Interrupt for 1 ms, A = 9, C = 4, B = 250
//Which means PR2 = 249, and # is x1001101 = 0x4D
T2CON = 0x4D;
PR2 = 249;
TMR2IE = 1;
PEIE = 1;
TMR2ON = 1;
TMR2IP = 1;
GIE = 1;
// While Loop displays length of Wait through Counter
while(1)
{
LCD_Move(0,0);
LCD_Out(COUNTER,3);
}
}
you need figure out how your button is connected to your microcontroller and declare that port in you main function. Make sure you are able to read the state of the port (i.e. button up or button down).
Then it your IntServe interrupt check if the button is down, if it is increment COUNTER.
The COUNTER is an integer, so it will only be able to count upto 65,535 ms (about 65 seconds), you may want to implement a second count variable for overflow, so that you can count button presses longer than 65 seconds.

PIC16F883 Led Blink

I need to program a PIC16F883 to blink / light up LED's at the same time. The oscillator is running at 3,2768, and I'm using TIMER0 to help me with the timing.
Right now, I have a prescaler set to 1:256, so I get an interrupt every 50ms, and I have a variable that is calculated from that, to display how many seconds has gone.
If the input is changed, the seconds variable is of course reset again.
Here is the assignment from my teacher:
If Input is 0 (Closed):
The Red And The Green LED should be turned on at the same time for 15 seconds. After this the green LED should be turned
off completely, and the red LED should blink every fifth second for 10 minutes
If input is 1 (Opened):
The red LED should be turned off completely, and the green LED should be turned on for 10 minutes, and after that
it should be turned off too.
My timer is working fine. I have tested that. The program runs fine too and keeps the 2 LED's turned off for 15 seconds, then turns them off, but my red LED isn't blinking. I have been sitting at my desk all day desperately trying to find the error in my code.
Picture of the print:
Here is my C Code. I am using MPLab and the HI-TECH C compiler :)
#include <pic.h>
//Variabler
int B = 0; //Definerer variablen B, used as a flag
int A = 0; //Definerer veriablen A, used as a flag
int E = 0;
int savedstatus = 1; //Definere variablen savedstatus used to check last status for input
int millicounter = 0; //Variabel to calculate seconds
int sec = 0; //Variabel holding seconds gone
int count = 0; //For counting seconds passed, used in input0 subroutine
int onesec = 0; //Used to counting seconds for blinking LED in input0 subroutine
int scount = 0;
//Variabler slut
void interrupt jesper(void)
{
T0IF = 0x00;
TMR0 = 96;
millicounter++;
if(millicounter == 20)
{
sec++;
millicounter = 0;
}
}
//Subrutines
void input0()
{
if(sec<=15 && E==0)
{
PORTA = 0x21;
}
else if(A==0)
{
scount = 0;
sec = 0;
count = sec;
A = 1;
E = 1;
}
else if(sec<=600 && sec>count)
{
count++;
if((scount+5)>=count)
{
if(B==0)
{
onesec = sec;
B = 1;
PORTA = 0x01;
}
else if(sec>onesec)
{
PORTA = 0x00;
B = 0;
scount = count;
scount;
}
else
{
PORTA = 0x01;
}
}
else
{
PORTA = 0x00;
}
}
else PORTA = 0x00;
}
void input1()
{
if(sec<=600)
{
PORTA = 0x20;
}
else
{
PORTA = 0x00;
}
}
//Subrutines over
int main(void)
{
TRISA = 0x00; //Sets all A-PORTS to output
TRISB = 0x01; //Sets all PORTB to output with the exception of BIT0
TRISC = 0x00; //Sets All PORTC to output
ANSEL = 0x00; //Disable Analog ports
ANSELH = 0x00; //Disable Analog ports
//Timer Config
PSA = 0x00;
PS0 = 0x01;
PS1 = 0x01;
PS2 = 0x01;
TMR0 = 0x60;
GIE = 0x01;
T0IE = 0x01;
T0IF = 0x00;
T0CS = 0x00;
//Timer Config Over
while(0x01)
{
if(savedstatus != RB0)
{
savedstatus = RB0;
sec = 0;
E = 0;
A = 0;
}
if(savedstatus == 1)
{
input1();
}
else
{
input0();
}
}
}
I really hope that you can help me here :)
Here is my flowchart for the subroutine input0 where my problem is. Btw some of my variables have different names in the code itself, but it shouldn't be hard to see.
Your main() calls input0() as often as possible. When input0() is in the flashing state it uses the conditional sec > count. I suspect that your intention is that input0() should only change the LED state at intervals of a second. But then on the else side of that conditional you turn both LEDs off. This else side is executing many times because main() is calling input0() so often. Try deleting the else condition where you turn the LEDs off.
void input0()
{
<snip>
else if(sec<=600 && sec>count)
{
<snip>
}
else PORTA = 0x00; // <-- delete this line so you're not always turning the LED off
}

An issue that might lay in the code which I don't see (using a ledstrip) Atmel Studio 6.1

I am using Atmel Studio 6.1 and this is the code that I use, beside this i also got another code called "ledstrip.h". Which basically is an 1 dimensional array.
This is something for my study.
I am trying to send 12 bytes through a 'ledstrip'
code:
#define SPI_SS_bm PIN4_bm
#define SPI_MOSI_bm PIN5_bm
#define SPI_MISO_bm PIN6_bm
#define SPI_SCK_bm PIN7_bm
#define MIN_VALUE 0.4
#define F_CPU 32000000UL
#define P 128
#define FOO 0
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "ledstrip.h"
void spi_init(void);
uint8_t spi_transfer(uint8_t data);
const uint8_t *ptr = image;
uint8_t num[12];
int line;
int g;
int data;
int i;
void row (const uint8_t *j)
{
uint32_t row2 = 0;
for(g = 0; g < 4; g++)
{
for(int i = 0; i < 8; i++)
{
row2 = (row2 << 3) | pgm_read_byte(j);
j++;
}
num[3*g] = (uint8_t) (row2 >> 16); //put bytes in the right order
num[3*g+1] = (uint8_t) (row2 >> 8);
num[3*g+2] = (uint8_t) (row2);
}
}
void spi_initialisation(void)
{
PORTC.DIRSET = SPI_SCK_bm|SPI_MOSI_bm|SPI_SS_bm;
PORTC.DIRCLR = SPI_MISO_bm;
SPIC.CTRL = (!SPI_CLK2X_bm) | // no double clock speed
SPI_ENABLE_bm | // SPI enable
!SPI_DORD_bm | // data order, MSB first
SPI_MASTER_bm | // master
SPI_MODE_0_gc | // mode 0
SPI_PRESCALER_DIV4_gc; // Presc. 4 (#2 MHz,500kHz)
}
void spi_init(void)
{
PORTC.DIRSET = PIN7_bm|PIN5_bm|PIN4_bm; // 7: MOSI 5: SCK
PORTC.OUTCLR = PIN4_bm; // 4: latch enable
PORTD.DIRSET |= PIN3_bm|PIN1_bm; // 3: MOSI 1: SCK
USARTC1.BAUDCTRLA = 0; // baud rate FCPU/2
USARTC1.BAUDCTRLB = 0; //
USARTC1.CTRLC = USART_CMODE_MSPI_gc; // SPI mode
USARTC1.CTRLA = 0; // no interrupts
USARTC1.CTRLB = USART_TXEN_bm; // enable transmit
USARTD0.BAUDCTRLA = 0; // baud rate FCPU/2
USARTD0.BAUDCTRLB = 0; //
USARTD0.CTRLC = USART_CMODE_MSPI_gc; // SPI mode
USARTD0.CTRLA = 0; // no interrupts
USARTD0.CTRLB = USART_TXEN_bm; // enable transmit
}
void init_timer_phi(void)
{
TCE0.CTRLA = TC_CLKSEL_DIV8_gc; // prescaling P
TCE0.CTRLB = TC_WGMODE_NORMAL_gc; // normal mode
TCE0.INTCTRLA = TC_OVFINTLVL_LO_gc;
TCE0.PER = 1440; // t = PER*FCPU/P =
// FCPU*P/32M = 1 us
}
ISR (TCE0_OVF_vect)
{
ptr = ptr +32;
if(ptr >= image + 32 * 360)
{
ptr = image;
} // send bytes to ledstrip
}
void init_inputcapture(void)
{
PORTC.PIN2CTRL = PORT_ISC_FALLING_gc;
PORTC.DIRCLR = PIN2_bm; // Pin 2 is input
EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN2_gc; // Select PC2 as input
// to event channel 0
TCC0.CTRLD = TC_EVACT_CAPT_gc | // Event capture
TC_EVSEL_CH0_gc; // for Channel 0
TCC0.CTRLB = TC0_CCAEN_bm; // Enable Inp. Capt. Ch. A
TCC0.CTRLA = TC_CLKSEL_DIV256_gc; // Start timer
TCC0.INTCTRLB = TC_CCAINTLVL_LO_gc; // Set Interr. level Ch. A
TCC0.PER = 0xFFFF;
}
ISR(TCC0_CCA_vect)
{
uint16_t v;
v = TCC0.CCA;
if (v > MIN_VALUE)
{ // skip if measured value is too small
line = 0; // reset image
TCE0.PER = (v * 360/(F_CPU / P)); // calculate periode
TCC0.CTRLFSET = TC_CMD_RESTART_gc; // restart input capture
}
}
void spi_write_byte(uint8_t data)
{
PORTC.OUTCLR = SPI_SS_bm;
spi_transfer(data);
PORTC.OUTSET = SPI_SS_bm;
}
uint8_t spi_read_byte(void)
{
uint8_t data;
PORTC.OUTCLR = SPI_SS_bm;
data = spi_transfer (FOO);
PORTC.OUTSET = SPI_SS_bm;
return data;
}
int main(void)
{
uint8_t i = 0;
spi_init();
PORTC.DIRSET = PIN0_bm;
PMIC.CTRL |= PMIC_LOLVLEN_bm;
sei();
PORTC.DIRSET = PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm;
while(1)
{
SPIC.DATA = i; // send i
while( ! (SPIC.STATUS & (SPI_IF_bm)) ); // wait until send
PORTC.OUTSET = PIN0_bm; // store
PORTC.OUTCLR = PIN0_bm;
_delay_ms(100);
i++;
}
}
Okay, so I got this code with no errors and warnings.
But when I run the program on my microcontroller ATXMega128A4U, I don't get the intended output.
There is a possibility that I didn't connect the pins of my 'ledstrip' in the right way with the pins of the microcontroller.
But if we consider that I did it like I intended to, the problem should be in the code.
The intended signal is 12 bytes long and with that I can turn RGB LED's on or off.
The RGB LED's are put together in a so called 'ledstrip'
Now what I'm getting is that some of the RGB LED's turn on and are Red Green or Blue.
What i should be getting is something like a chasing RGB LED row.
So you would see the LED's turn on or off at a certain frequency.

8051 c interrupts

I'm using C to write a program on an 8051 microcontroller. The compiler I'm using is Keil Microvision. I'm stuck and having trouble figuring out what is missing from my code. I know it's very basic code I just can't figure out what I'm supposed to do.
So pretty much what I am doing is taking sending a sentence out to the user and having them answer yes or no through the serial port and I used a serial interrupt. That part works fine. If I get a no from the person I want to generate a square wave 5kHz by a timer interrupt. I want this square wave to be controlled by an external interrupt turning it on and off when the external interrupt on pin P3.2 is either on or off.
Here is all my code
#include <REG52.H>
#include <stdio.h>
sbit WAVE = P1 ^ 7;
#define BIT(x) (1 << (x))
void timer0() interrupt 1 // timer is controlling square wave timer 0
{
WAVE = ~WAVE;
}
void interrupt0() interrupt 0
{
IE ^= BIT(1);
}
void serial0() interrupt 4
{
unsigned char x;
unsigned int i, z;
unsigned char yes[] = " YES ";
unsigned char no[] = " NO ";
unsigned char nvalid[] = " NOT VALID TRY AGAIN ";
while (RI == 1) {
x = SBUF;
RI = 0;
if (z < 1) {
if (x == 'n') {
for (i = 0; i < 4; i++) {
SBUF = no[i];
while (TI == 0) ; //wait for transmit
TI = 0;
z++;
}
}
} else {
return;
}
if (x == 'y') {
for (i = 0; i < 5; i++) {
SBUF = yes[i];
while (TI == 0) ;
TI = 0;
}
} else if (x != 'n') {
for (i = 0; i < 21; i++) {
SBUF = nvalid[i];
while (TI == 0) ;
TI = 0;
}
}
TI = 0;
return;
}
}
void main()
{
TMOD = 0x20;
TH1 = 0xF6; //baud rate
SCON = 0x50;
TH0 = 0xA4;
IE = 0x93; //enable interrupts
IP = 0x10; // propriety to serial interrupt
TR1 = 1; //start timer 1
TR0 = 1; //clear timer 0
TI = 1;
printf("Hello, Are you okay? Press y for yes and n for no ");
while (1) ;
}
The part I'm having trouble with is these two interrupt from the previous code
void timer0() interrupt 1 // timer is controlling square wave timer 0
{
WAVE=~WAVE;
}
void interrupt0() interrupt 0
{
IE ^= BIT(1);
}
Any hints in the right direction would be greatly appreciated! Thanks. Sorry about formatting
Variables that are modified by interrupts should be defined as volatile:
volatile sbit WAVE = P1 ^ 7;

Resources