Digits not displayed properly, Unable to control output at particular pin - c

I am trying to display my input at microcontroller ATmega16 to 7 segment displays.
I have found the following code on http://www.avr-tutorials.com/projects/atmega16-based-digital-clock but when I implimented it, it is not working. I am getting a fluctuating output i.e I am not able to control the output at particular pins.
I have two inputs temp1 and temp2, and I want to display each of them on three 7-segment displays. Also, I have not used Pins 2 & 3 as they are interrupt pins and I have used them somewhere else. Pin0,1,4,5,6,7 are used.
The code works fine when some delay is added, otherwise output is generated at random pins.
i.e. The output which I was suppose to display from PIND1 is displayed on all pins,
My code:
#include <avr/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define SegDataPort PORTC
#define SegDataPin PINC
#define SegDataDDR DDRC
#define SegCntrlPort PORTD
#define SegCntrlPin PIND
#define SegCntrlDDR DDRD
/*
* Function Description:
* Encode a Decimal Digit 0-9 to its Seven Segment Equivalent.
*
* Function Arguments:
* digit - Decimal Digit to be Encoded
* common - Common Anode (0), Common Cathode(1)
* SegVal - Encoded Seven Segment Value
*
* Connections:
* Encoded SegVal is return in the other G-F-E-D-C-B-A that is A is the least
* significant bit (bit 0) and G bit 6.
*/
unsigned char DigitTo7SegEncoder(int digit, unsigned char common)
{
unsigned char SegVal;
switch(digit)
{
case 0: if(common == 1) SegVal = 0b00111111;
else SegVal = ~0b00111111;
break;
case 1: if(common == 1) SegVal = 0b00000110;
else SegVal = ~0b00000110;
break;
case 2: if(common == 1) SegVal = 0b01011011;
else SegVal = ~0b01011011;
break;
case 3: if(common == 1) SegVal = 0b01001111;
else SegVal = ~0b01001111;
break;
case 4: if(common == 1) SegVal = 0b01100110;
else SegVal = ~0b01100110;
break;
case 5: if(common == 1) SegVal = 0b01101101;
else SegVal = ~0b01101101;
break;
case 6: if(common == 1) SegVal = 0b01111101;
else SegVal = ~0b01111101;
break;
case 7: if(common == 1) SegVal = 0b00000111;
else SegVal = ~0b00000111;
break;
case 8: if(common == 1) SegVal = 0b01111111;
else SegVal = ~0b01111111;
break;
case 9: if(common == 1) SegVal = 0b01101111;
else SegVal = ~0b01101111;
}
return SegVal;
}
int main(void)
{
int temp1,temp2;
//Suppose my input is 105 and 210, i.e. temp1=105 and temp2=210;
// it contains other information also, not required here
SegDataDDR = 0xFF;
SegCntrlDDR = 0xF3;
SegCntrlPort = 0xF3;
SegDataPort = 0x00;
while(1){
SegDataPort = DigitTo7SegEncoder(temp1%10,1);
SegCntrlPort = ~0x01;
SegDataPort = DigitTo7SegEncoder((temp1/10)%10,1);
SegCntrlPort = ~0x02;
SegDataPort = DigitTo7SegEncoder(temp1/100,1);
SegCntrlPort = ~0x10;
SegDataPort = DigitTo7SegEncoder(temp2%10,1);
SegCntrlPort = ~0x20;
SegDataPort = DigitTo7SegEncoder((temp2/10)%10,1);
SegCntrlPort = ~0x40;
SegDataPort = DigitTo7SegEncoder(temp2/100,1);
SegCntrlPort = ~0x80;
}}

You don't set the DDRs to output anywhere. The pins you want to use as outputs must have the corresponding bit in DDRx set to 1. Otherwise it remains an input pin.
An input pin will show an output, but with a lower current and a more slowly rising edge. Drawing on that current with an LCD may cause the voltage to drop.

Provided that these 7-segment components don't contain any sequential logic inside this is what actually happens:
SegDataPort = DigitTo7SegEncoder(temp1%10,1); // You write the data
SegCntrlPort = ~0x01; // You enable the first 7-segment component
// Then without any delay...
SegDataPort = DigitTo7SegEncoder((temp1/10)%10,1); // You write other data
SegCntrlPort = ~0x02; // You enable the second component
// The without any delay...
So actually the 7-segment component displays previous and next digits at once for a short time.
What about this? (just a pseudocode)
SegCntrlPort = 0xFF; // hide everything
SetDataPort = ... value1 ...;
SegCntrlPort = ~0x01; // show it
WaitForAWhile();
SegCntrlPort = 0xFF; // hide everything to avoid unwanted transitions
SetDataPort = ... value2 ...;
SegCntrlPort = ~0x02; // show it
WaitForAWhile();
And so on.

Related

PIC24 Evaluation Board always returns 1 when reading input from pins [resolved]

I am trying to set up a function which will read digital input from pins on a PIC24 MCU and use the bits that are read to reconstruct a full value. The MCU can properly receive and send values over UART and output these to a parallel bus, but now I am trying to read into the bus and the pins will always read 1 regardless of whether or not a voltage is present at the pins. I cannot figure out why this is and would appreciate some help if anyone has any insight. These are the functions I am using:
void configureReadPins()
{
//configuring pins for bus
TRISAbits.TRISA9 = 1; //configure A9 as input
TRISCbits.TRISC3 = 1; //configure C3 as input
TRISCbits.TRISC4 = 1; //configure C4 as input
TRISCbits.TRISC5 = 1; //configure C5 as input
TRISBbits.TRISB5 = 1; //configure B5 as input
TRISBbits.TRISB6 = 1; //configure B6 as input
TRISBbits.TRISB7 = 1; //configure B7 as input
TRISBbits.TRISB8 = 1; //configure B8 as input
//Setting Read pin to output and Write pin to input
TRISBbits.TRISB12 = 0;
TRISBbits.TRISB13 = 1;
}
void readFromFPGA()
{
configureReadPins();
int i = 0;
int bitcount = 0;
int pin = 0;
int index = 0;
uint16_t addressRead = 0;
uint16_t sampleRead = 0;
uint16_t comparisonSample = 0;
//LATBbits.LATB12 = 1; //tell FPGA MCU is ready to read
//while(PORTAbits.RA1 != 1); //wait for FPGA to set clock pin high in order to start reading the contents of the bus
while (index < 1024 && (numSamples != readCounter))
{
comparisonSample = dataArray1[index];
//reading sample point
for (i = 0; i < 2; i++)
{
for (bitcount = 0; bitcount < 8; bitcount++)
{
switch (bitcount)
{
case 7:
pin = PORTAbits.RA9;
sampleRead += pin;
break;
case 6:
pin = PORTCbits.RC3;
sampleRead += pin;
break;
case 5:
pin = PORTCbits.RC4;
sampleRead += pin;
break;
case 4:
pin = PORTCbits.RC5;
sampleRead += pin;
break;
case 3:
pin = PORTBbits.RB5;
sampleRead += pin;
break;
case 2:
pin = PORTBbits.RB6;
sampleRead += pin;
break;
case 1:
pin = PORTBbits.RB7;
sampleRead += pin;
break;
case 0:
pin = PORTBbits.RB8;
sampleRead += PORTBbits.RB8;
break;
}
//reads in value from left to right in bits
//AKA case 0 will read RB8, which gives MSB value of 8 bits received
if (i == 0 || (i == 1 && bitcount != 7) )
sampleRead <<= 1; //shift next bit to left to get in proper place
pin = 0;
}
}
sampleRead = 0;
index++;
}
In all cases, the values of pin is set to 1 after reading from the MCU's pins. Any idea why this is happening?
edit: The problem was I left the pins floating. Since they weren't connected to ground, the transistors used for the pins kept the previous high voltage so the pins were not reading as expected. Once the pins expected to read 0 were connected to ground they read the expected value of 0.

Code for 4-Digit 7-Segment Display: Why doesn't code work for 2 of 4 digits?

I have written 2 functions (gpio_write & gpio_set_function) to be able to control the digits and segments of a 7-Segment Display (Common Anode LED), that is connected to my RPi via Bipolar Junction Transistors: Collector to common power, base to RPi pins via 1 kOhm resistor, and emitter to digit nodes on the display (image here).
The segments are connected directly to pins on the RPi.
The code successfully lights up digits 1 & 3, (and all segments) but digits 2 and 4 do not light up. I need some help figuring out why that is.
I have double & triple checked the wiring, made sure the digits are connected to pins 10 thru 13, and the segments to pins 20 thru 26 (period to pin 27). I have checked the code as well, and couldn't find a problem with it. I have also made sure that each of the digits actually works by disconnecting from the RPi and lighting up each of the segments on each digit independently (Segment B of Digit 3 is burned, all the others work).
What could be another issue that would cause digits 2 and 4 not to light up? Or perhaps something IS wrong with the code?
#include "timer.h"
#include "gpio.h"
void gpio_set_function(unsigned int pin, unsigned int function) {
unsigned int mask = 7;
if ( (pin < GPIO_PIN_FIRST || pin > GPIO_PIN_LAST) || (function < GPIO_FUNC_INPUT || function > GPIO_FUNC_ALT3) )
;
else{
switch (pin/10){
case 0:
*GP_FSEL0 &= ~((mask)<<(3*pin));
*GP_FSEL0 |= function<<(3*pin);
break;
case 1:
pin = pin%10;
*GP_FSEL1 &= ~((mask)<<(3*pin));
*GP_FSEL1 |= function<<(3*pin);
break;
case 2:
pin = pin%20;
*GP_FSEL2 &= ~((mask)<<(3*pin));
*GP_FSEL2 |= (function<<(3*pin));
break;
case 3:
pin = pin%30;
*GP_FSEL3 &= ~((mask)<<(3*pin));
*GP_FSEL3 |= function<<(3*pin);
break;
case 4:
pin = pin%40;
*GP_FSEL4 &= ~((mask)<<(3*pin));
*GP_FSEL4 |= function<<(3*pin);
break;
default:
;
}
}
}
void gpio_write(unsigned int pin, unsigned int value) {
if ( (pin < GPIO_PIN_FIRST || pin > GPIO_PIN_LAST) || (value < 0 || value > 1) ) ;
else {
switch (pin/32){
case 0:
if (value==1){
*GP_FSET0 &= ~(1<<pin);
*GP_FSET0 |= 1<<pin;
}
else
*GP_CLR0 |= 1<<pin;
break;
case 1:
if (value==1){
*GP_FSET1 &= ~(1<<(pin-32));
*GP_FSET1 |= 1<<(pin-32);
}
else
*GP_CLR1 |= 1<<(pin-32);
break;
default:
;
}
}
}
void main(void) {
volatile int i;
for(i = 10; i < 14 ; i++)
gpio_set_function(i, GPIO_FUNC_OUTPUT);
for(i = 19; i < 27 ; i++)
gpio_set_function(i, GPIO_FUNC_OUTPUT);
while (1){
for(i = 10; i < 14 ; i++)
gpio_write(i, 1);
for(i = 19; i < 27; i++)
gpio_write(i, 0);
for (volatile int delay = 0xF0000; delay != 0; delay--);
for(i = 10; i < 14 ; i++)
gpio_write(i, 0);
for (volatile int delay = 0x0000F; delay != 0; delay--);
}
}
ADDITIONAL ATTEMPT:
I tried simplifying the code by not using any functions. Still getting the same result. All segments work on digits 1 and 3. Digits 2 and 4 do not light up.
void main(void) {
// set functions
unsigned int mask = 7;
*GP_FSEL1 &= ~((mask)<<(3*1)); // reset pin 11
*GP_FSEL1 |= GPIO_FUNC_OUTPUT<<(3*1); // set pin 11 to OUTPUT
*GP_FSEL2 &= ~((mask)<<(3*0)); // reset pin 20
*GP_FSEL2 |= GPIO_FUNC_OUTPUT<<(3*0); // set pin 20 to OUTPUT
*GP_FSET0 &= ~(1<<11); // reset SET Reg of pin 11
*GP_FSET0 |= 1<<11; // set SET Reg of pin 11 to high
*GP_CLR0 &= ~(1<<20); // reset CLR Reg of pin 20
*GP_CLR0 |= 1<<20; // set CLR Reg of pin 20 to high
}

If vs Case. If incrementing strangely

I'm learning embedded programming, and have a LED board and button board hooked up to the same PORT.
The commented out if statement under the chk_button function, certain buttons when activated will add to the num variable its intended increment + 1. IE: pushing button 1 will increment num by three. The current case statement works to spec.
I understand case statements when compiled effectively become look up tables, and thus have smaller footprint and run faster,but I am uncertain as to WHY im getting the bug that I am.
I'm also open to any other criticisms in my code.
// HARDWARE SETUP:
// PORTA is connected to the segments of the LED display. and to the pushbuttons.
// PORTA.0 corresponds to segment a, PORTA.1 corresponds to segement b, etc.
// PORTB bits 4-6 go to a,b,c inputs of the 74HC138.
// PORTB bit 7 goes to the PWM transistor base.
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 16000000
#define DIGIT_ONE 0x00
#define DIGIT_TWO 0x10
#define DIGIT_COLON 0x20
#define DIGIT_THREE 0x30
#define DIGIT_FOUR 0x40
//******************************************************************************
// debounce_switches
//Checks the state of the button number passed to it. It shifts in ones till
//the button is pushed. Function returns a 1 only once per debounced button
//push so a debounce and toggle function can be implemented at the same time.
//Adapted to check all buttons from Ganssel's "Guide to Debouncing"
//Expects active low pushbuttons on PINA port. Debounce time is determined by
//external loop delay times 12.
//Saves status of button (i) into a state array.
//******************************************************************************
int8_t debounce_switches(uint16_t *state, uint8_t i) {
state[i] = (state[i] << 1) | (! bit_is_clear(PINA, i)) | 0xE000;
if (state[i] == 0xF000) return 1;
return 0;
}
//******************************************************************************
// chk_buttons
//Checks the buttons. Calls debounce_switches in a loop passing both the state array
//and the current switch being checked.
//If debounce_switches returns a 1 for a switch, case statements determine which switch
//was activated, and increments count by the appropriate value.
//******************************************************************************
void chk_buttons(uint16_t *state, uint16_t *num)
{
uint8_t itr;
for( itr=0; itr<8; itr++)
{
if( debounce_switches(state, itr))
{
switch(itr)
{
case 0:
*num += 1;
break;
case 1:
*num += 2;
break;
case 2:
*num += 4;
break;
case 3:
*num += 8;
break;
case 4:
*num += 16;
break;
case 5:
*num += 32;
break;
case 6:
*num += 64;
break;
case 7:
*num +=128;
break;
}
/*
if (itr == 0) *num += 1;
else if(itr == 1) *num += 2;
else if(itr == 2) *num += 4;
else if(itr == 3) *num += 8;
else if(itr == 4) *num += 16;
else if(itr == 5) *num += 32;
else if(itr == 6) *num += 64;
else if(itr == 7) *num += 128;
*/
}
}
}
//******************************************************************************
// itoseven
// Accepts a number from 0 -9 Returns a hex value to display on the seven segment..
//******************************************************************************
uint8_t itoseven(uint8_t num)
{
uint8_t segnum;
switch(num)
{
case 0:
segnum = ~0x3F;
return segnum;
case 1:
segnum = ~0x06;
return segnum;
case 2:
segnum = ~0x5B;
return segnum;
case 3:
segnum = ~0x4F;
return segnum;
case 4:
segnum = ~0x66;
return segnum;
case 5:
segnum = ~0x6D;
return segnum;
case 6:
segnum = ~0x7D;
return segnum;
case 7:
segnum = ~0x07;
return segnum;
case 8:
segnum = ~0x7F;
return segnum;
case 9:
segnum = ~0x6F;
return segnum;
}
}
//***********************************************************************************
// segment_sum
//takes a 16-bit binary input value and displays the result to the LED board.
//***********************************************************************************
void segsum(uint16_t num) {
uint8_t ones;
uint8_t tens;
uint8_t hundreds;
uint8_t thousands;
//break up decimal sum into 4 digit-segments
ones = num % 10;
tens = (num/10)%10;
hundreds = (num/100)%10;
thousands = (num/1000)%10;
//determine how many digits there are
if(num < 10)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(num);
}
else if(num > 9 && num <100)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(ones);
_delay_ms(2);
PORTB = DIGIT_TWO;
PORTA = itoseven(tens);
}
else if(num > 99 && num < 1000)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(ones);
_delay_ms(2);
PORTB = DIGIT_TWO;
PORTA = itoseven(tens);
_delay_ms(2);
PORTB = DIGIT_THREE;
PORTA = itoseven(hundreds);
}
else if (num >999)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(ones);
_delay_ms(2);
PORTB = DIGIT_TWO;
PORTA = itoseven(tens);
_delay_ms(2);
PORTB = DIGIT_THREE;
PORTA = itoseven(hundreds);
_delay_ms(2);
PORTB = DIGIT_FOUR;
PORTA = itoseven(thousands);
}
}
uint8_t main()
{
DDRB = 0xF0; //set port bits 4-7 B as outputs
uint16_t num = 0;
uint16_t state[8];
//initialize array values for debouncing
for(int i=0; i<8; i++)
{
state[i]= 0;
}
while(1)
{
//make PORTA an input port with pullups
DDRA = 0x00;
PORTA = 0xFF;
//enable tristate buffer for pushbutton switches
PORTB = 0x70;
//check the buttons. Increment by appropriate value if switch is active.
chk_buttons(&state, &num);
//rollover at 1023
if(num > 1023)
num = 1;
//switch PORTA to output
DDRA = 0xFF;
//Send num to display
segsum(num);
_delay_ms(2);
}
return 0;
}
I've update these functions to remove the switches as they are not needed at all. Note how the first uses an algorithm in place of a switch and the second uses a table that is easy to adjust in the future. Also, assert/error check your inputs and you'll be a happier camper when things go sideways.
void chk_buttons(uint16_t *state, uint16_t *num)
{
// Assert bad state and num here.
uint8_t itr;
for( itr=0; itr<8; itr++)
{
if( debounce_switches(state, itr))
{
*num += 1 << itr; // Could also use |= as that is what we are doing.
}
}
}
uint8_t itoseven(uint8_t num)
{
// assert num <= 9
const uint8_t kLookup[10] =
{~0x3f, ~0x06, ~0x5B, ~0x4F, ~0x66,
~0x6D, ~0x7D, ~0x07, ~0x7F, ~0x6F};
return kLookup[num];
}
For the last function, if you start at the 4-digit number check and work backwards to the single digit, it becomes a very simple loop to do your complex digit calculation. Just divide your mask from 10,000 to 10. I'll post that code a bit later as I have time.
Update
Here is something I coded up that demonstrates the idea. You will need to modify it for your own functions as right now it just outputs ASCII. It fails for negative numbers (as does your code), but that is very easy to add with a simple if check / ABS / prepend a minus character.
int main(void)
{
int num = 9876;
// Starting at the 5th digit. You could use 1000 instead if
// there were only 4 digits or less ever.
int digitMask = 10000;
char output[16];
int index = 0;
// Handle 0 case.
if(num== 0)
{
output[index++] = '0';
}
else
{
// Skip leading 0's
while((num / digitMask) == 0)
{
digitMask /= 10;
}
// While there may be digits to process...
while(digitMask)
{
// Grab MS Digit and mod it away from total.
int digit = num / digitMask;
num %= digitMask;
// Convert to ASCII (you would use your own function)
output[index++] = digit + '0';
// Update mask - note we could use a for/loop here just as easily.
digitMask /= 10;
}
}
// Terminate string and print it.
output[index] = 0;
printf("%s", output);
return 0;
}

Malfunctioning concurrent tick functions in my state machine

The purpose of the code I'm writing is that when my 0th bit of PINA is 1, the number displayed on PORTB is incremented. Likewise, if the 1st bit of PINA is 1, the number is decremented. If the button is held down, it will increment/decrement at a rate of once per second. If the button has been held down for at least 3 seconds, the rate is increased to one every 400 ms. If both buttons are pressed, the number displayed on PORTB is reset to 0. The timer period is set at 100 ms.
I split the state machine into 2 state machines running "concurrently". One SM adjusts the period that I'm incrementing/decrementing at, and the other does the transitions between waiting/adding/subtracting/resetting states.
The problem I'm having is that my state machine that modifies the period is not doing anything at all. I have a global variable to keep track of how many ticks (initialized to 10) I have to wait before incrementing/decrementing, and that this machine should modifying it when the number of ticks stayed in my Incr/Decr states exceeded 30 ticks (3 seconds). But this machine is not doing anything at all. I modified so that it will immediately and permanently change to 4 ticks when my concurrent SM starts, but that still doesn't do anything; incrementing/decrementing is still happening every 1 second rather than every 400 ms.
What's wrong with my code?
Code in question:
enum States {Init, ButPres, Incr, Wait, Decr, Reset} state;
enum other_States {Init1, change_tick_total} state1;
unsigned char button = 0x00;
unsigned char cnt = 0x00;
unsigned char tick_cnt = 0;
unsigned char tick_total = 0x0A;
void change_period_tick() {
switch (state1) {
case Init1:
state = change_tick_total;
break;
case change_tick_total:
state = change_tick_total;
break;
default:
state = Init1;
break;
}
switch (state1) {
case change_tick_total:
if (tick_cnt > 30)
tick_total = 0x04;
else
tick_total = 0x0A;
break;
default:
break;
}
}
void tick(){
switch(state){
case Init:
state = ButPres;
break;
case ButPres:
if(button == 0x01)
state = Incr;
else if(button == 0x02)
state = Decr;
else if(button == 0x03)
state = Reset;
else
state = ButPres;
break;
case Incr:
if(button == 0x01 && cnt < 9)
state = Incr;
else
state = Wait;
break;
case Decr:
if(button == 0x02 && cnt > 0){
state = Decr;
}
else
state = Wait;
break;
case Wait:
if(button == 0x03)
state = Reset;
else if(button)
state = Wait;
else
state = ButPres;
break;
case Reset:
if(button == 0x03)
state = Reset;
else
state = Init;
break;
default:
state = Init;
break;
}
switch(state){
case Init:
cnt = 0x00;
PORTB = cnt;
break;
case Incr:
if(cnt < 0x09){
++tick_cnt;
if (tick_cnt % tick_total == 1)
++cnt;
PORTB = cnt;
}
break;
case Decr:
if(cnt > 0x00){
++tick_cnt;
if (tick_cnt % tick_total == 1)
--cnt;
PORTB = cnt;
}
break;
case Reset:
cnt = 0;
PORTB = cnt;
default:
tick_cnt = 0; //once we're out of INCR/DECR, the tick_cnt resets, as we're on a new cycle of counting ticks
break;
}
}
int main(void)
{
state = Init;
state1 = Init1;
DDRA = 0x00; PORTA = 0xFF;
DDRB = 0xFF; PORTB = 0x00;
// Initializes the LCD display
TimerSet(100);
TimerOn();
tick_total = 0x0A;
while(1) {
button = ~PINA;
change_period_tick(); //this does no seem to be running at all
tick();
while(!TimerFlag){}
TimerFlag = 0;
}
}

How do I properly reset buffer so next read is correct?

My project involves sending commands from PuTTY to a Dragon12-Plus2 development board(CodeWarrior 5.1) via an XBEE Wifi. I am using 4 commands to control the leds on the Dragon board {led_enable(), leds_on(integer in hex or decimal here), leds_off(), and led_disable()} from the LBE_DRAGON12_Plus project from LBEbooks.com. Here is my code:
// Final Project: Control leds via XBEE Wifi
#include <hidef.h> /* common defines and macros */
#include <mc9s12dg256.h> /* derivative information */
#include "queue.h"
#pragma LINK_INFO DERIVATIVE "mc9s12dg256b"
#include "main_asm.h" /* interface to the assembly module */
void main(void){
int x,y,z,parser;
int cmdLen = 0;
char c,d,e;
char cbuff[20];
PLL_init(); // set system clock frequency to 24 MHz
lcd_init(); // enable lcd
SCI1_init(9600); // initialize SCI1 at 9600 baud
SCI0_init(9600); // initialize SCI0 at 9600 baud
seg7_disable(); // disable 7 segment display
led_enable(); // enable 8 leds
while(1){
if(SCI1SR1_RDRF == 1){
c = inchar1();
cbuff[cmdLen] = c;
outchar0(cbuff[cmdLen]);
if(c == ';'){
if((cbuff[0] == 'l') && (cbuff[10] == ';')){
leds_off();
cmdLen = 0;
}
else if((cbuff[0] == 'l') && (cbuff[12] == ';')){
led_enable();
cmdLen = 0;
}
else if((cbuff[0] == 'l') && (cbuff[4] == 'd')){
led_disable();
cmdLen = 0;
}
else if((cbuff[0] == 'l') && (cbuff[13] == ';')){
d = cbuff[10];
e = cbuff[11];
switch(d){ // change first number to integer
case('0'):
x = 0x00;
break;
case('1'):
x = 0x10;
break;
case('2'):
x = 0x20;
break;
case('3'):
x = 0x30;
break;
case('4'):
x = 0x40;
break;
case('5'):
x = 0x50;
break;
case('6'):
x = 0x60;
break;
case('7'):
x = 0x70;
break;
case('8'):
x = 0x80;
break;
case('9'):
x = 0x90;
break;
case('a'):
x = 0xa0;
break;
case('b'):
x = 0xb0;
break;
case('c'):
x = 0xc0;
break;
case('d'):
x = 0xd0;
break;
case('e'):
x = 0xe0;
break;
case('f'):
x = 0xf0;
break;
default:
break;
}
switch(e){ // change second number to integer
case('0'):
y = 0x00;
break;
case('1'):
y = 0x01;
break;
case('2'):
y = 0x02;
break;
case('3'):
y = 0x03;
break;
case('4'):
y = 0x04;
break;
case('5'):
y = 0x05;
break;
case('6'):
y = 0x06;
break;
case('7'):
y = 0x07;
break;
case('8'):
y = 0x08;
break;
case('9'):
y = 0x09;
break;
case('a'):
y = 0x0a;
break;
case('b'):
y = 0x0b;
break;
case('c'):
y = 0x0c;
break;
case('d'):
y = 0x0d;
break;
case('e'):
y = 0x0e;
break;
case('f'):
y = 0x0f;
break;
default:
break;
}
z = (x + y); // add integers together
leds_on(z); // display hex number on leds
cmdLen = 0; // reset parser
}
for(parser = 0; parser < 20; parser++){
cbuff[parser] = '\0';
}
}
cmdLen++;
}
}
}
The first command i send works as expected (for instance if i type leds_on(0xaa); in PuTTY the 4 corresponding leds light up), but any command I send after does nothing. I am not sure how to properly reset cbuff so that it operates the same way each time, not just the first time.
EDITED TO SHOW SUGGESTED CHANGES!
If you want to clear all of the elements in the array, then memset would be a wise choice:
memset(cbuff, 0, 20);
That being said, I would strongly agree with #John Bollinger that separating the input and the interpretation functionality would be wise.
However, depending on the application memset might be overkill. A simple cleared array may also be achieved by simply setting the elements of the array to null character ('\0'). Simply call cbuff[0] = '\0' for each element in the array.
What an odd parser. I'd suggest you separate your input stage from your command interpretation stage. That is, read and count characters until you receive a semicolon (;) command terminator, and only then try to interpret the command.
Reset the parser variable (which would more accurately be named something like command_length) only after each attempt to interpret the command, whether successful or not, or if the buffer is about to overflow.

Resources