Working serial connection!

hello world

I got the Hello World! Finally serial communication part is working, next part is to get display refreshing and sift register writing to work efficiently as it must be constantly multiplexed. devscreen

And this is how I develop AVR code. Pretty eh?

And code that produces “Hello World!” output:

/* Ketturi Fox 2013
 * File:	main.c
 * Project: VFD Driver
 * Project folder: https://www.dropbox.com/sh/24stwfan7eqthdz/DxebGKKUiF
 * 
 */

#ifndef F_CPU
//#define F_CPU     18432000UL // 18.432 Mhz 
#define F_CPU   16000000UL // 16 Mhz
#endif 

#define USART_BAUDRATE 	19200 //UART baud rate, 19200 works with 16Mhz clock, 38400 works too(tested)

#include <inttypes.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

// Macros for bit manipulation
#define SET_BIT(target, bit) ((target) |=   _BV((unsigned char) (bit)))
#define CLR_BIT(target, bit) ((target) &= ~(_BV((unsigned char) (bit))))

#define DISPLAY_SIZE 32 //digits
#define LONG_DELAY  450 //Delays for multiplexing
#define SHORT_DELAY  50 //need to be made interrupts/something useful during delays

/*                   
* Font for segments
* generated with kukkafontti by magnificent hauvakukka
*/                   
// First byte  == PORT_A
// Second byte == PORT_C
//{ (d,c,e,g2,g1,f,b,a),(n/c,i,j,h,m,k,l,dp) },
// ASCII, control charters not handled here, only for reference
//some charters, like 1-5 need to be re-purposed as ä,ö,Ä,Ö and forwarded from 132, 148, 142, 153
//handling d.p. should be rethough, now it leaves empty charter left to it
//darn I love ASCII <3
const unsigned char font[128][2] = {
	{ 0b00000000, 0b00000000 }, //NUL Null \0 ^@      (null charter, but shows as empty block dunno)
	{ 0b11111111, 0b01111111 }, //can be used like test charter lighting all segments
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 },
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, //ACK Acknowledge     (send for data successfully received)
	{ 0b00000000, 0b00000000 }, //BEL  Bell \a ^G     (make audible notification for email etc)
	{ 0b00000000, 0b00000000 }, //BS Backspace \b ^H  (remove last charter from textBuffer)
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, //LF Linefeed \n ~J   (clear textBuffer)
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, //FF Formfeed \f ^L   (clear textBuffer, for compatibly)
	{ 0b00000000, 0b00000000 }, //CR Carriage return \r ^M (Return "cursor" to first digit)
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, //DC1 Device control (Turn leds on/off or sumthing)
	{ 0b00000000, 0b00000000 }, //DC2
	{ 0b00000000, 0b00000000 }, //DC3
	{ 0b00000000, 0b00000000 }, //DC4
	{ 0b00000000, 0b00000000 }, //NAK neg. acknowledge (Houston, we have problem)
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, //ESC Escape \e ^[     (dunno, not needed)
	{ 0b00000000, 0b00000000 },  
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, 
	{ 0b00000000, 0b00000000 }, //" " space or empty block
	{ 0b01000010, 0b00000001 }, //"!"
	{ 0b00000100, 0b01000000 }, 
	{ 0b11011010, 0b01000010 }, 
	{ 0b11011101, 0b01000010 }, 
	{ 0b01000100, 0b00101000 }, 
	{ 0b11101001, 0b01010100 }, 
	{ 0b00000000, 0b00100000 }, 
	{ 0b00000000, 0b00100100 }, 
	{ 0b00000000, 0b00011000 }, 
	{ 0b00011000, 0b01111110 }, 
	{ 0b00011000, 0b01000010 }, 
	{ 0b00000000, 0b00001000 }, 
	{ 0b00011000, 0b00000000 }, 
	{ 0b00000000, 0b00000001 }, // "."    (light dot in display)
	{ 0b00000000, 0b00101000 }, 
	{ 0b11100111, 0b00101000 }, 
	{ 0b01000010, 0b00000000 }, //"0" 
	{ 0b10111011, 0b00000000 }, 
	{ 0b11011011, 0b00000000 }, 
	{ 0b01011110, 0b00000000 }, 
	{ 0b11011101, 0b00000000 }, 
	{ 0b11111101, 0b00000000 }, 
	{ 0b01000011, 0b00000000 }, 
	{ 0b11111111, 0b00000000 }, 
	{ 0b11011111, 0b00000000 }, 
	{ 0b00000000, 0b01000010 }, //"9"
	{ 0b00000000, 0b01001000 }, 
	{ 0b00000000, 0b00100100 }, 
	{ 0b10011000, 0b00000000 }, 
	{ 0b00000000, 0b00011000 }, 
	{ 0b00010011, 0b00000011 }, //"?"
	{ 0b11101011, 0b00000010 }, 
	{ 0b01111111, 0b00000000 }, //"A"
	{ 0b11010011, 0b01000010 }, 
	{ 0b10100101, 0b00000000 }, 
	{ 0b11000011, 0b01000010 }, 
	{ 0b10101101, 0b00000000 }, 
	{ 0b00101101, 0b00000000 }, 
	{ 0b11110101, 0b00000000 }, 
	{ 0b01111110, 0b00000000 }, 
	{ 0b10000001, 0b01000010 }, 
	{ 0b11100010, 0b00000000 }, 
	{ 0b00101100, 0b00100100 }, 
	{ 0b10100100, 0b00000000 }, 
	{ 0b01100110, 0b00110000 }, 
	{ 0b01100110, 0b00010100 }, 
	{ 0b11100111, 0b00000000 }, 
	{ 0b00111111, 0b00000000 }, 
	{ 0b11100111, 0b00000100 }, 
	{ 0b00111111, 0b00000100 }, 
	{ 0b11010001, 0b00010000 }, 
	{ 0b00000001, 0b01000010 }, 
	{ 0b11100110, 0b00000000 }, 
	{ 0b00100100, 0b00101000 }, 
	{ 0b01100110, 0b00001100 }, 
	{ 0b00000000, 0b00111100 }, 
	{ 0b00000000, 0b00110010 }, 
	{ 0b10000001, 0b00101000 }, //"Z"
	{ 0b10100101, 0b00000000 }, 
	{ 0b00000000, 0b00010100 }, 
	{ 0b11000011, 0b00000000 }, 
	{ 0b00000000, 0b00001100 }, 
	{ 0b10000000, 0b00000000 }, 
	{ 0b00000000, 0b00010000 }, 
	{ 0b10101000, 0b00000010 }, //"a"
	{ 0b10101100, 0b00000100 }, 
	{ 0b10111000, 0b00000000 }, 
	{ 0b11010010, 0b00001000 }, 
	{ 0b10101000, 0b00001000 }, 
	{ 0b00101101, 0b00000000 }, 
	{ 0b11010010, 0b00100000 }, 
	{ 0b00101100, 0b00000010 }, 
	{ 0b00000000, 0b00000010 }, 
	{ 0b11000010, 0b00000000 }, 
	{ 0b00000000, 0b01100110 }, 
	{ 0b00100100, 0b00000000 }, 
	{ 0b01111000, 0b00000010 }, 
	{ 0b00101000, 0b00000010 }, 
	{ 0b11111000, 0b00000000 }, 
	{ 0b00101100, 0b00010000 }, 
	{ 0b01010010, 0b00100000 }, 
	{ 0b00101000, 0b00000000 }, 
	{ 0b10010000, 0b00000100 }, 
	{ 0b10101100, 0b00000000 }, 
	{ 0b11100000, 0b00000000 }, 
	{ 0b01000000, 0b00000100 }, 
	{ 0b01100000, 0b00001100 }, 
	{ 0b00011000, 0b00001100 }, 
	{ 0b11000000, 0b00000100 }, 
	{ 0b10001000, 0b00001000 }, //"z"
	{ 0b10001001, 0b00011000 }, 
	{ 0b00000000, 0b01000010 }, 
	{ 0b10010001, 0b00100100 }, 
	{ 0b00000100, 0b00110000 }, 
	{ 0b11111111, 0b01111110 } //DEL    (also not needed, ignored charter"
};

/*
 * Port & device init
 */
void boot(void) {
	// Set port directions and pull-ups
	DDRA = 0b11111111;
	DDRC = 0b11111111;
	DDRB = 0b00001111;
}

void writeBitToShiftRegister(int bit){
/* Shiftregister configuration:
*Strobe (outputs enabled) PB0
*Latch enable (Latch clock) PB1
*Clock PB2
*Data In PB3
*
*Data is entered with L -> H clock edge
*While Latch Enable is H, Data -> Outputs
*Strobe puts outputs on when L. (can be tied to L)
*/

#define Strobe_PORT 	PORTB
#define Latch_PORT		PORTB
#define Clock_PORT		PORTB
#define Data_PORT		PORTB

#define Strobe_BIT		0
#define Latch_BIT		1
#define Clock_BIT		2
#define Data_BIT		3

	#define SET_Strobe ((Strobe_PORT) |= _BV(Strobe_BIT))
	#define CLR_Strobe ((Strobe_PORT) &= ~(_BV(Strobe_BIT)))

	#define SET_Latch ((Latch_PORT) |= _BV(Latch_BIT))
	#define CLR_Latch ((Latch_PORT) &= ~(_BV(Latch_BIT)))

	#define SET_Clock ((Clock_PORT) |= _BV(Clock_BIT))
	#define CLR_Clock ((Clock_PORT) &= ~(_BV(Clock_BIT)))

	#define SET_Data ((Data_PORT) |= _BV(Data_BIT))
	#define CLR_Data ((Data_PORT) &= ~(_BV(Data_BIT)))

	SET_Strobe;        //Put all outputs low
	  _delay_us(0.010);

	CLR_Latch;	      //Latch low(keep previoysly stored data in latch)
	  _delay_us(0.010);

	if (bit == 1)    //Load data from function to shift register input
		SET_Data;
	else 
		CLR_Data;
		_delay_us(0.150); //Setup time, DATA IN before rising CLOCK edge	

	CLR_Clock;	      //Start Clock cycle should last 1000ns
	  _delay_us(0.500); //Pulse furation, CLOCK High
	SET_Clock;        //End Clock cycle
	  _delay_us(0.500); //Pulse duration, CLOCK Low

	SET_Latch;		  //Move data to latch (New data in latch)
	CLR_Strobe;		  //Enable output buffers

}

unsigned char textBuffer[32]; //here goes the text on display

void refreshDisplay() {  //draws every digit to display, must be executed constantly

        int i;

        // Make sure everything is off.
        PORTA = 0;
        PORTC = 0;

        // Clear shift register to be sure.
        for (i = 0; i < DISPLAY_SIZE; i++) {
                writeBitToShiftRegister(0);
		}

        // Select first display digit.
        writeBitToShiftRegister(1);

        // Loop through all digits
        for (i = 0; i < DISPLAY_SIZE; i++) {

                // Read next character.
                // The character is masked to make sure it doesn't go outside font range.
                const unsigned char c = textBuffer[i] & 0b01111111;

                // Read bytes for corresponding segment configuration.
                const unsigned char byteA = font[c][0];
                const unsigned char byteB = font[c][1];

                // Turn segments on.
                PORTA = byteA;
                PORTC = byteB;

                // Wait. interrupt/other stuff here, delay is stupid
                _delay_us(LONG_DELAY);

                // Turn segments off.
                PORTA = 0;
                PORTC = 0;

                // Wait.
                _delay_us(SHORT_DELAY);

                // Prepare for next display module.
                writeBitToShiftRegister(0);
        }
}

void uart_init(uint16_t baudrate) {
	UBRRL = baudrate;
	UBRRH = (baudrate >> 8);
	UCSRC = (1 << URSEL) | (3 << UCSZ0);
	UCSRB = (1 << RXEN) | (1 << TXEN); // Enable RX and TX
}

void uart_putchar(char c) { //puts one charter to serial send buffer
    loop_until_bit_is_set(UCSRA, UDRE); // Wait until data register empty.
    UDR = c;
}

char uart_getchar(void) { //gets 1 charter from serial receive buffer
    loop_until_bit_is_set(UCSRA, RXC); // Wait until data exists.
    return UDR;
}

int main(void){
//textBuffer = "Hello World!                    ";
//refreshDisplay();

//loop here to get charter from uart_getchar();
//and put it to textBuffer, and then refreshDisplay();
//interrupts etc. stuff would be nice 
uart_init((((F_CPU / (USART_BAUDRATE * 16UL))) - 1)); //initialize uart at calculated baudrate

while(1){
	uart_putchar('H');
	uart_putchar('e');
	uart_putchar('l');
	uart_putchar('l');
	uart_putchar('o');
	uart_putchar(' ');
	uart_putchar('w');
	uart_putchar('o');  //just stupid testing
	uart_putchar('r');
	uart_putchar('l');
	uart_putchar('d');
	uart_putchar('!');
	uart_putchar('\n');
	uart_putchar('\r');
	}
return 0;
}

 

You should put your comment here!

This site uses Akismet to reduce spam. Learn how your comment data is processed.