5

I'm designing a click counter for a microcontroller and I'm using C for developing the code.

What happens here is when I click first button it will count the number of button presses. Then I have to press the second button to display the count in binary lighting up the LEDs. For example, if I press first button 10 times, it will light up second LED and fourth LED.

Since there are 8 LEDs I'm using 2 different ports.( 6 bits from PORTB and 2 bits from PORTD). For that I have developed a code using if/else.But I want to implement this operation without multiple if/else operations because this method doesn't seem like much efficient.

while(PIND & 0b00100000){                   //while PD5 switch is not pressed
        if(clickCount>=128){                //if click count>=128
            PORTB = PORTB | 0b00100000;     //set PB5 HIGH
            clickCount-=128;                //deduct 128 from clickCount
        }else if(clickCount>=64){
            PORTB = PORTB | 0b00010000;
            clickCount-=64;
        }else if(clickCount>=32){
            PORTB = PORTB | 0b00001000;
            clickCount-=32;
        }else if(clickCount>=16){
            PORTB = PORTB | 0b00000100;
            clickCount-=16;
        }else if(clickCount>=8){
            PORTB = PORTB | 0b00000010;
            clickCount-=8;
        }else if(clickCount>=4){
            PORTB = PORTB | 0b00000001;
            clickCount-=4;
        }else if(clickCount>=2){
            PORTD = PORTD | 0b10000000;
            clickCount-=2;
        }else if(clickCount==1){
            PORTD = PORTD | 0b01000000;
            clickCount = 0;
        }           
    }

And I want to make this code in less number of bytes. So is there any way to develop this code segment using a for loop or any other method?

dunu008
  • 105
  • 1
  • 15

3 Answers3

3

I don't know if this reduces the binary size, and not tested. You can still do something like this:

 unsigned char mask[] = {
     0b01000000, 0b10000000, 0b00000001, 0b00000010,
     0b00000100, 0b00001000, 0b00010000, 0b00100000};
 while(PIND & 0b00100000) {
     for (int i = 7, v = 128; i > -1; --i, v /= 2) {
         if (clickCount >= v && clickCount > 0) {
             if (clickCount >= 4) {
               PORTB = PORTB | mask[i];
             } else {
               PORTD = PORTD | mask[i];
             }
             clickCount -= v;
             break;
         }
     }
 }

Or you can use a single loop:

int v = 128, i = 7;
while (v > 0 && (PIND & 0b00100000)) {
    if (clickCount >= v) {
         if (clickCount >= 4) {
           PORTB = PORTB | mask[i];
         } else {
           PORTD = PORTD | mask[i];
         }
        clickCount -= v;
    } else {
        --i;
        v /= 2;
    }
}
perreal
  • 94,503
  • 21
  • 155
  • 181
  • Since I am using interrupts to handle the button clicks I will have to change your code. – dunu008 Nov 03 '18 at 05:29
  • Actually you don't need to use if/else or any other loops to implement this.I have mentioned it in my answer below. – dunu008 May 24 '19 at 10:32
3

This could be done by just assigning values to PORTB and PORTD seperately since you have the number of clicks stored in a variable-clickCounter.

PORTB = PORTB | (clickCount & 0b00111111);
PORTD = PORTD | (clickCount & 0b11000000);
dunu008
  • 105
  • 1
  • 15
1

To handle the output, I would do something like:

clickCount %= 256; /* because the output is 8-bit */
PORTB = clickCount;

To make the output exactly 1 instruction long:

unsigned char clickCount = 0;

... /* do things, handle increment, handle 2nd button */

PORTB = clickCount; /* modulo 256 no longer needed, ClickCount cannot be more than 8 bits anyway */

I see no reason for doing it bit by bit.

virolino
  • 2,073
  • 5
  • 21
  • yes, you can seperately assign the values to the ports as you have mentioned here. – dunu008 May 24 '19 at 10:02
  • Then you can implement it in 2 simple operations, instead of countless operations. Of course, you need to handle the increment of the conter and the second button additionally. – virolino May 24 '19 at 10:04
  • Here you can only use 1 port.But in my answer we can use different ports as we need. – dunu008 May 24 '19 at 10:13
  • When doing embedded work, it is always best to optimize everything which can be optimized. Of course you can even use 8 ports, but it is not worth. It is more worth to alter the hardware design (early enough in the project), rather than finding flexible solutions in software. – virolino May 24 '19 at 10:33
  • Yes sure.But I had used other pins for several other purposes. – dunu008 May 24 '19 at 10:38
  • It is in your best interest to change the usage of the pins, in order to have a full port for the output. Otherwise, your answer is the next best answer. – virolino May 24 '19 at 10:40