I have taken ths code from a very old thread on AVR Freaks.
https://www.avrfreaks.net/sites/default/files/Encoder.c
Compiled it for Atmega 32.
I want to make a coil winding , decremental counter starting from the number set on the four digits of seven segment display. (this is the first step to the final requirement.)
The display can be set to the desired number, but to set a number in thousands the spins on the encoder are plenty!
Can the button on the encoder be used to select a digit with every press to set the number on that digit.
Encoder is connected to PD2 and PD0. Switch not used
Seven Segment are connected to PB0.......PB6. DP not used.
PC4...PC7 select the ones,tens,hundreds and thousands digit.
//Code for Atmega32 @ 16 MHz
/Code taken from url https://www.avrfreaks.net/sites/default/files/Encoder.c
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <math.h>
#include <util/delay.h>
#define CHECKBIT(x,y) (x & (y)) /* Check bit y in byte x*/
#define SETBIT(x,y) (x |= (y)) /* Set bit y in byte x*/
#define CLEARBIT(x,y) (x &= (~y)) /* Clear bit y in byte x*/
//lookup table ascii char to 7 segment common anode type with pullup resistors
//static const uint8_t PROGMEM sevsegascii_table[] = {
// 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xbf // 0 1 2 3 4 5 6 7 8 9 -
//};
//lookup table ascii char to 7 segment common anode type without pullup resistors
static const uint8_t PROGMEM sevsegascii_table[] = {
0x3F, 0x6, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x7, 0x7F, 0x6F, 0x40 // 0 1 2 3 4 5 6 7 8 9 -
};
void displayNumber(int number);
void printNumber(int number);
volatile int num;
volatile int ones;
volatile int tens;
volatile int hundreds;
volatile int thousands;
int main(void)
{
DDRB = 0xff; // sets port b as output
PORTB = 0x00; // sets all bis on port B low
DDRD = 0x00; //input port
PORTD = 0xFF; //enable pull up resistor
DDRC = 0xff;
PORTC = 0x10;
TCCR0 |= (1<< CS02); //256 PRESCALER
TCCR0 |= (1<< WGM01); //CTC MODE
OCR0 = 130; //8ms. setting how fast to refresh the display
MCUCR = 0x01; //int0 interrupt on level change
//MCUCR |= (1<<ISC00); // int0 interrupt on level change
GICR = 0x40;// enable int0 interrupt. This uses 2 bytes less
//as compard to next commented statement
//GICR |= 1<<INT0; //enable the int0 interrupt.
TIMSK |= (1<<OCIE0); //enable the timer0 compare interrupt
sei(); //enable global interrupts
num = 10; //initializing the "counter"
while(1)
{
printNumber(num);
}
return 0;
}
void printNumber(int number)
{
int temp = 0;
//splitting the number into separate numbers
//to display on the 4 digit 7-segment display
thousands = floor(number / 1000);
temp = number % 1000;
hundreds = floor(temp/100);
temp = number % 100;
tens = floor(temp/10);
ones = temp % 10;
}
//displaying the number on the 7 segment display
void displayNumber(int number)
{
if (number<0) {
number*=-1;
}
PORTB = pgm_read_byte(&sevsegascii_table[number]);
}
ISR(TIMER0_COMP_vect)
{
//selecting which digit to display
//timing controlled by Timer0
switch(PORTC)
{
case 0x80:
displayNumber(hundreds);
PORTC = 0x40;
break;
case 0x40:
displayNumber(tens);
PORTC = 0x20;
break;
case 0x20:
displayNumber(ones);
PORTC = 0x10;
break;
case 0x10:
displayNumber(thousands);
PORTC = 0x80;
break;
default:
break;
}
}
ISR(INT0_vect)
{
/* this works for MCUCR=0x01 i.e. interrupt on level change */
// A raising edge
if ((PIND & (1<<PD2))) {
if ((PIND & (1<<PD0))) num++; // B rising edge
else num--; // B falling edge
}
// A raising edge
else {
if ((PIND & (1<<PD0))) num--; // B rising edge
else num++; // B falling edge
}
}
Will be greatful for inputs toward this endeavour.