This is an old revision of the document!
/* Basic ver 3 demo program 7-seg function and demo Raivo Sell/Erki Leitaru */ #define F_CPU 14745600UL #include <avr/io.h> #include <util/delay.h> #define SET(x) |= (1<<x) //defineeritakse kõrge bit pordis x #define CLR(x) &=~(1<<x) //defineeritakse madal bit pordis x #define bit_get(p,m) ((p) & (m)) //returns 1 if bit is set, otherwise returns 0 #define BIT(x) (0x01 << (x)) void write_display (void); void nop_delay(int count); int i;//for cycle int digit;//digit to display on segment int nr;//segment map representation of the digit int delta;//to create a counting effect int num = 0; char buffer[7]; void nop_delay(int count){ unsigned int j; for (j=0; j<count;j++) {asm volatile ("nop");} } void write_display (void) { switch (digit) //table read to get segment map representation of the digit { case 0 : nr = 0b00111111;break; //every bit corresponds to one segment case 1 : nr = 0b00000110;break; //"1" case 2 : nr = 0b01011011;break; //"2" and so on case 3 : nr = 0b01001111;break; case 4 : nr = 0b01100110;break; case 5 : nr = 0b01101101;break; case 6 : nr = 0b01111100;break; case 7 : nr = 0b00000111;break; case 8 : nr = 0b01111111;break; case 9 : nr = 0b01100111;break; default: nr = 0b01111001;//E } PORTG CLR (2); //latch low for(i=7; i>=0; i--) //for every bit in the byte { //if bit is set, sets the data out pin if (bit_get(nr, BIT(i))) PORTC SET (6); //serial out else PORTC CLR (6); //serial out PORTC SET (7); //clock high nop_delay(8);//series of one cycle delays to ensure required timing (according to datasheet) PORTC CLR (7); //clock low nop_delay(8); } PORTG SET (2); //latch high } int main(void){ //7-seg init PORTC = 0xFF; // set output high -> turn all LEDs off DDRC = 0xF8; // PC0...PC2 -> input; PC3...PC5 -> output for LED; PC7 & PC6 outputs for clock and data DDRG = 0x04;//PG2 is latch output digit = 8; delta = 1;//increment or decrement while(1) { num++; _delay_ms(1000); digit=digit+delta;//change digit by delta if(digit>8) {delta=-1*delta;};//upper limit if(digit<1) {delta=-1*delta;};//lower limit write_display(); } }
this example does not contain global variables and only functions are used. It is more easy to copy the functions into user program. All variables are 8 bit where possible.
// // Simple up/down counting single 7-segment digit example. // // Raivo Sell, Erki Leitaru, Mikk Leini // // 2009 // #define F_CPU 14745600UL // Include avrlibc #include <avr/io.h> #include <util/delay.h> // Macros for bit manipulation #define BIT(x) (1 << (x)) #define SET(x) |= BIT(x) #define CLR(x) &= ~BIT(x) #define SETTO(value, bit, to) value = ((to) ? value | BIT(bit) : value & ~BIT(bit)) #define ISSET(value, bit) ((value) & (BIT(bit))) // // Delay cycle // On each cycle "no-operation" instruction is executed // void nop_delay(unsigned int count) { for (unsigned int i = 0; i < count; i++) { asm volatile ("nop"); } } // // 7 segment display initialization // void segment_diplay_init(void) { // Port C pin 7 - clock output, pin 6 data output DDRC |= 0xC0; // Port G pin 2 - latch output DDRG |= 0x04; } // // Digit writing to 7 segment display // void segment_display_write(unsigned char digit) { unsigned char map; // Decimal to segment map switch (digit) { case 0 : map = 0b00111111; break; // Every bit corresponds to one segment case 1 : map = 0b00000110; break; // "1" case 2 : map = 0b01011011; break; // "2" case 3 : map = 0b01001111; break; // "3" and so on case 4 : map = 0b01100110; break; case 5 : map = 0b01101101; break; case 6 : map = 0b01111100; break; case 7 : map = 0b00000111; break; case 8 : map = 0b01111111; break; case 9 : map = 0b01100111; break; default: map = 0b01111001; // E like Error } // Latch low PORTG CLR(2); // Send every bit in the byte. MSB (most significant bit) first. for (signed char i = 7; i >= 0; i--) { // If bit is set, sets the data out pin, otherwise not SETTO(PORTC, 6, ISSET(map, i)); // Clock high for certain period PORTC SET(7); nop_delay(8); // Clock low for certain period PORTC CLR(7); nop_delay(8); } // Latch high PORTG SET(2); } // // Program entrance function // int main(void) { unsigned char digit = 0; // Digit to display on segment signed char delta = 1; // Digit modifying value // 7 segment display initialization segment_diplay_init(); // Endless loop while (1) { // Write digit segment_display_write(digit); // Increase digit value by delta (which can be negative also) digit += delta; // Swap counting direction on 0 and 9 if (digit == 0) delta = +1; if (digit == 9) delta = -1; // Wait 1000 ms _delay_ms(1000); } }
“pinops.h” library is used to simplify the port and pin usage. See here for more detail description.
LED driver is replaced by the avrlibc driver.
// // Simple up/down counting single 7-segment digit example. // // Raivo Sell, Erki Leitaru, Mikk Leini // // 2009 // // Include avrlibc #include <avr/io.h> #include <util/delay.h> // Include common library #include "pinops.h" /* PS! For distance Lab use: #include <util/pinops.h> */ // Configure pins #define SEGMENT_DISPLAY_LATCH PORTPIN(G, 2) #define SEGMENT_DISPLAY_DATA_OUT PORTPIN(C, 6) #define SEGMENT_DISPLAY_CLOCK PORTPIN(C, 7) // // 7 segment display initialization // void segment_display_init(void) { // Set latch, data out and clock pins as output setup_output_pin(SEGMENT_DISPLAY_LATCH); setup_output_pin(SEGMENT_DISPLAY_DATA_OUT); setup_output_pin(SEGMENT_DISPLAY_CLOCK); } // // Digit writing to 7 segment display // void segment_display_write(unsigned char digit) { unsigned char map; // Decimal to segment map switch (digit) { case 0 : map = 0b00111111; break; // Every bit corresponds to one segment case 1 : map = 0b00000110; break; // "1" case 2 : map = 0b01011011; break; // "2" case 3 : map = 0b01001111; break; // "3" and so on case 4 : map = 0b01100110; break; case 5 : map = 0b01101101; break; case 6 : map = 0b01111100; break; case 7 : map = 0b00000111; break; case 8 : map = 0b01111111; break; case 9 : map = 0b01100111; break; default: map = 0b01111001; // E like Error } // Latch low clear_pin(SEGMENT_DISPLAY_LATCH); // Send every bit in the byte. MSB (most significant bit) first. for (signed char i = 7; i >= 0; i--) { // If bit is set, sets the data out pin, otherwise not set_pin_to(SEGMENT_DISPLAY_DATA_OUT, IS_BIT_SET(map, i)); // Clock high for certain period set_pin(SEGMENT_DISPLAY_CLOCK) _delay_us(1); // Clock low for certain period clear_pin(SEGMENT_DISPLAY_CLOCK) _delay_us(1); } // Latch high set_pin(SEGMENT_DISPLAY_LATCH); } // // Program entrance function // int main(void) { unsigned char digit = 0; // Digit to display on segment signed char delta = 1; // Digit modifying value //digit = int (void) { return 2; }; // 7 segment display initialization segment_display_init(); // Endless loop while (1) { // Write digit segment_display_write(digit); // Increase digit value by delta (which can be negative also) digit += delta; // Swap counting direction on 0 and 9 if (digit == 0) delta = +1; if (digit == 9) delta = -1; // Wait 1000 ms _delay_ms(1000); } }