User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

c:avr-sample [2018-08-01 16:32] (current)
Line 1: Line 1:
 +{{ :​c:​sunfounder-electronic-diy-robotic-arm-kit-4-axis-servo-control-rollarm-with-wired-controller-for-arduino.jpg?​240|}}
  
 +=====AVR MCU pure C sample====
 +
 +Sample for Arduino interactive "​application"​. ​
 +I wrote for the weekend from chip datasheet and examples.
 +
 +In general, I bought a kit of manipulator for my youngest son, but once I got a micro controller ... I could not miss this chance and "​remember all" =)
 +
 +Into the sample release:
 +  - FIFO buffers for input and input/​output to serial line
 +  - Redirect standard ​ input/​output to FIFOs
 +  - 2 PWN output ​
 +  - Watchdog and timer interrupts (I hooked FIFO in/out to the interrupts)
 +  - Some own data manipulation function
 +  - ... What yet? 
 +
 +The microprocessor is very modest for 2017 but I liked simplicity (relative) of its programming.
 +
 +===Output===
 +<​code>​
 +# cu -s 38400 -l /dev/ttyU0
 +Connected
 +#########################​
 +### UNIX7.ORG ##############​
 +READY>23
 +OK 23   
 +READY>
 +</​code>​
 +
 +<code make Makefile>​
 +#
 +# $Id$
 +#
 +.SECONDARY:
 +
 +all: main.hex
 +
 +CFLAGS= -I. -Os -DF_CPU=16000000UL -mmcu=atmega328p
 +LDFLAGS= -s -Os -DF_CPU=16000000UL -mmcu=atmega328p
 +
 +main.elf: main.o fifo.o tools.o
 + avr-gcc $(LDFLAGS) -o $@ main.o fifo.o tools.o
 +
 +%.o: %.c
 + avr-gcc $(CFLAGS) -c -o $@ $<
 +
 +%.elf: %.o
 + avr-gcc $(LDFLAGS) -o $@ $<
 +
 +%.hex: %.elf
 + avr-objcopy --strip-unneeded -g -O ihex -R .eeprom $< $@
 +
 +upload: main.hex
 + avrdude -qq -c arduino -p ATMEGA328P -P /dev/ttyU0 -b 115200 -U flash:​w:​main.hex
 +
 +backup:
 + avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyU0 -b 115200 -U flash:​r:​backup.hex:​i
 +
 +clean:
 + rm -f *.i *.o *.elf *~
 +
 +#EOF
 +</​code>​
 +
 +===fifo.c===
 +
 +<code C fifo.c>
 +/* $Id$ */
 +
 +#include <​ctype.h>​
 +#include <​stdint.h>​
 +#include <​stddef.h>​
 +#include <​stdbool.h>​
 +#include <​string.h>​
 +#include <​unistd.h>​
 +
 +#include <​fifo.h>​
 +
 +void fifo_init(FIFO * b, uint8_t * buffer, uint8_t buffer_len) {
 +    if (b && buffer) {
 +        memset((void **)buffer, 0, buffer_len);​
 +        b->​buffer_len = buffer_len;
 +        b->​buffer = buffer;
 +        b->head = 0;
 +        b->tail = 0;
 +    }
 +    return;
 +}
 +
 +uint8_t fifo_count(const FIFO * b) {
 +    if (b) {
 +        return (b->head - b->​tail);​
 +    }
 +    return 0;
 +}
 +
 +static bool fifo_full(const FIFO * b) {
 +    if (b) {
 +        return (fifo_count(b) == b->​buffer_len);​
 +    }
 +    return true;
 +}
 +
 +bool fifo_empty(const FIFO * b) {
 +    if (b) {
 +        return (fifo_count(b) == 0);
 +    }
 +    return true;
 +}
 +
 +uint8_t fifo_peek(const FIFO * b) {
 +    if (b) {
 +        return (b->​buffer[b->​tail % b->​buffer_len]);​
 +    }
 +    return 0;
 +}
 +
 +uint8_t fifo_getc(FIFO * b) {
 +    uint8_t data = 0;
 +
 +    if (!fifo_empty(b)) {
 +        data = b->​buffer[b->​tail % b->​buffer_len];​
 +        b->​tail++;​
 +    }
 +    return data;
 +}
 +
 +bool fifo_putc(FIFO * b, uint8_t data) {
 +    bool status = false;
 +
 +    if (b) {
 +        if (!fifo_full(b)) {
 +            b->​buffer[b->​head % b->​buffer_len] = data;
 +            b->​head++;​
 +            status = true;
 +        }
 +    }
 +    return status;
 +}
 +
 +uint8_t fifo_puts(FIFO * b, char *string) {
 +    if (b) {
 +        for (uint8_t i = 0; i < strlen(string);​ i++) {
 +            if (!fifo_putc(b,​ string[i]))
 +                return i;
 +        }
 +    }
 +}
 +
 +bool fifo_scanc(FIFO * b, uint8_t c) {
 +    if (b) {
 +        if (!fifo_empty(b)) {
 +            uint8_t tail = b->tail;
 +
 +            for (uint8_t i = 0; i < fifo_count(b);​ i++) {
 +                uint8_t data = b->​buffer[tail % b->​buffer_len];​
 +
 +                if (data == c) {
 +                    return true;
 +                }
 +                tail++;
 +            }
 +        }
 +        return false;
 +    }
 +}
 +
 +uint8_t fifo_gett(FIFO * b, uint8_t * str, uint8_t len, uint8_t term) {
 +    if (b) {
 +        memset((void *)str, 0, len);
 +
 +        if (fifo_scanc(b,​ term) && str) {
 +            uint8_t i = 0, c = 0;
 +
 +            while ((c = fifo_getc(b)) != 0 && c != term && i < len) {
 +                str[i] = c;
 +                i++;
 +            }
 +            return i;
 +        }
 +        return 0;
 +    }
 +}
 +/* EOF */
 +</​code>​
 +===fifo.h===
 +
 +<code C fifo.h>
 +/* $Id$ */
 +
 +#ifndef UARTH_IUI
 +#define UARTH_IUI
 +
 +struct fifo_t {
 +    volatile unsigned head;
 +    volatile unsigned tail;
 +    volatile uint8_t *buffer;
 +    unsigned buffer_len;
 +};
 +
 +typedef struct fifo_t FIFO;
 +
 +void fifo_init(FIFO * b, uint8_t * buffer, uint8_t buffer_len);​
 +uint8_t fifo_count(const FIFO * b);
 +static bool fifo_full(const FIFO * b);
 +bool fifo_empty(const FIFO * b);
 +uint8_t fifo_peek(const FIFO * b);
 +uint8_t fifo_getc(FIFO * b);
 +bool fifo_putc(FIFO * b, uint8_t data);
 +uint8_t fifo_puts(FIFO * b, char *string);
 +bool fifo_scanc(FIFO * b, uint8_t c);
 +uint8_t fifo_gett(FIFO * b, uint8_t * str, uint8_t len, uint8_t);
 +
 +#endif
 +/* EOF */
 +</​code>​
 +===main.c===
 +
 +<code C main.c>
 +/* $Id$ */
 +
 +#include <​ctype.h>​
 +#include <​stdint.h>​
 +#include <​stdio.h>​
 +#include <​stddef.h>​
 +#include <​stdbool.h>​
 +#include <​string.h>​
 +#include <​unistd.h>​
 +
 +#include <​avr/​io.h>​
 +#include <​avr/​wdt.h>​
 +#include <​avr/​interrupt.h>​
 +#include <​avr/​pgmspace.h>​
 +#include <​util/​delay.h>​
 +
 +
 +#define BAUD 38400
 +#include <​util/​setbaud.h>​
 +
 +#include <​fifo.h>​
 +#include <​tools.h>​
 +
 +inline void init_uart(void) {
 +    /* UBRR - USART Baud Rate Register */
 +    UBRR0H = UBRRH_VALUE;​
 +    UBRR0L = UBRRL_VALUE;​
 +    /* UCSR  - USART Control and Status Register */
 +    /* U2X - Double Speed Operation */
 +    UCSR0A &= ~(1 << U2X0);
 +    /* UCSZ - USART Character Size, 8 bit */
 +    UCSR0B &= ~(1 << UCSZ02);
 +    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
 +    /* USBS - USART Stop Bit Select */
 +    /* UPM - USART Parity Mode */
 +    UCSR0C &= ~(1 << USBS0) & ~(1 << UPM00) & ~(1 << UPM01);
 +    UCSR0B |= (1 << TXEN0) | (1 << RXEN0);
 +    UCSR0B |= (1 << RXCIE0); ​   /* Enable Receive Interrupt */
 +    UCSR0B &= ~(1 << UDRIE0); ​  /* Disabale Transmit Interrupt */
 +}
 +
 +void wdt_init(void) {
 +    wdt_enable(WDTO_30MS);​
 +    WDTCSR = (1 << WDIE);
 +}
 +
 +#define FIFO_BUFFER_SIZE 255
 +
 +FIFO fifo_in, fifo_out;
 +FIFO* in;
 +FIFO* out;
 +
 +ISR(USART_RX_vect) {
 +    uint8_t c = UDR0;
 +    if (c == '​\r'​) {
 +        fifo_puts(in,​ "​\n"​);​
 +        fifo_puts(out,​ "​\n"​);​
 +    }
 +    fifo_putc(in,​ c);
 +    fifo_putc(out,​ c);
 +}
 +
 +//​ISR(USART_UDRE_vect) {
 +//}
 +
 +ISR(WDT_vect) {
 +    wdt_reset();​
 +    uint8_t c;
 +    while ((c = fifo_getc(out)) > 0) {
 +        while (!(UCSR0A & (1 << UDRE0)));
 +            UDR0 = c;
 +    }
 +    WDTCSR = (1 << WDIE);
 +}
 +
 +#define CLKD1    (1<<​CS20) ​     /* CLK/8 */
 +#define CLKD8    (1<<​CS21) ​     /* CLK/8 */
 +#define CLKD32 ​  ​(1<<​CS20)|(1<<​CS21) ​   /* CLK/32 */
 +#define CLKD64 ​  ​(1<<​CS22); ​    /* CLK/64 */
 +#define CLKD128 ​ (1<<​CS20)|(1<<​CS22) ​   /* CLK/128 */
 +#define CLKD256 ​ (1<<​CS21)|(1<<​CS22) ​   /* CLK/256 */
 +#define CLKD1024 (1<<​CS20)|(1<<​CS21)|(1<<​CS22) ​ /* CLK/1024 */
 +
 +void timer_init(void) {
 +    TCCR2A = 0;
 +    TCCR2B = 0;
 +    TCCR2B = CLKD256;
 +    TIMSK2 |= (1 << TOIE2);
 +}
 +
 +void pwm_init(void) {
 +    TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00) | _BV(WGM01); ​
 +    TCCR0B = CLKD128;
 +    OCR0A = 0;
 +    OCR0B = 0;
 +    DDRB |= (1 << PORTB3) ;
 +    DDRD |= (1 << PORTD3) | (1 << PORTD6) | (1 << PORTD5) ;
 +}
 +
 +ISR(TIMER2_OVF_vect) {
 +}
 +
 +int uart_putchar(char c, FILE *stream) {
 +    return fifo_putc(&​fifo_out,​ c);
 +}
 +
 +int uart_getchar(FILE *stream) {
 +    return (int)fifo_getc(&​fifo_out);​
 +}
 +
 +FILE uart_str = FDEV_SETUP_STREAM(uart_putchar,​ uart_getchar,​ _FDEV_SETUP_RW);​
 +
 +int main() {
 +
 +    uint8_t inbuf[FIFO_BUFFER_SIZE];​
 +    uint8_t outbuf[FIFO_BUFFER_SIZE];​
 +
 +    stdout = stdin = stderr = &​uart_str;​
 +
 +    in = &​fifo_in;​
 +    out = &​fifo_out;​
 +
 +    fifo_init(in,​ inbuf, FIFO_BUFFER_SIZE);​
 +    fifo_init(out,​ outbuf, FIFO_BUFFER_SIZE);​
 +
 +    init_uart();​
 +    wdt_init();
 +    timer_init();​
 +    pwm_init();
 +    sei();
 +
 +    _delay_ms(1000);​
 +
 +    fifo_puts(out,​ "############################​\r\n"​);​
 +    fifo_puts(out,​ "### UNIX7.ORG ##############​\r\n"​);​
 +
 +    fifo_puts(out,​ "​READY>"​);​
 +
 +#define STR_LEN 64
 +    uint8_t str[STR_LEN];​
 +    memset(str, 0, STR_LEN);
 +
 +    while (1) {
 +        uint8_t *s;
 +        s = str;
 +
 +        while(fifo_gett(in,​ str, STR_LEN, '​\r'​) > 0) {
 +
 +            s = str_trim(str,​ ' ');
 +            int16_t i = str_geti(s);​
 +            int_gets(i, s, STR_LEN, 10);
 +
 +            if (i >= 10 && i <= 38) {
 +                OCR0A = i;
 +                OCR0B = i;
 +                fifo_puts(out,​ "OK ");
 +                fifo_puts(out,​ s);
 +            } else {
 +                fifo_puts(out,​ "OUT OF RANGE 10-38"​);​
 +            }
 +
 +            fifo_puts(out,​ "​\n\rREADY>"​);​
 +
 +        }
 +        _delay_ms(100);​
 +
 +    }
 +}
 +</​code>​
 +===tools.c===
 +
 +<code C tools.c>
 +/* $Id$ */
 +
 +#include <​stdint.h>​
 +#include <​tools.h>​
 +
 +uint16_t str_len(uint8_t * str) {
 +    uint16_t i = 0;
 +    while (str[i] != 0 && i < MAX_LINE_LEN)
 +        i++;
 +    return i;
 +}
 +
 +uint8_t *str_trim(uint8_t * str, uint8_t c) {
 +    while (str[0] == c && str[0] != 0) str++;
 +
 +    uint8_t i = str_len(str) - 1;
 +    while (str[i] == c && i > 0) {
 +        i--;
 +    }
 +    str[++i] = 0;
 +    return str;
 +}
 +
 +int32_t int_power(uint8_t n, uint8_t s) {
 +    int64_t i = 1;
 +    while (s--) {
 +        i = i * n;
 +    }
 +    return i;
 +}
 +
 +int32_t str_geti(uint8_t * str) {
 +    uint8_t l = str_len(str);​
 +    uint8_t i = l - 1;
 +    int16_t n = 0;
 +    while (i--) {
 +        if (str[i] <= '​9'​ && str[i] >= '​0'​)
 +            n += (str[i] - '​0'​) * int_power(10,​ l - i - 2);
 +    }
 +    if (str[0] == '​-'​) n = -n;
 +    return n;
 +}
 +
 +uint8_t int_gets(int32_t num, uint8_t *str, uint8_t str_len, int16_t base) {
 +    static char digits[] = "​0123456789abcdefghijklmnopqrstuvwxyz";​
 +    uint8_t i = 0, sign = 0;
 +    if (num < 0) {
 +        sign = '​-';​
 +        num = -num;
 +    }
 +    do {
 +        str[i++] = digits[num % base];
 +    } while ((num /= base) > 0 && i < str_len);
 +
 +    if (sign) str[i++] = '​-';​
 +    str[i] = 0;
 +
 +    uint8_t len = i - 1;
 +    uint8_t c, b = 0;
 +
 +    while(i-- && b < i) {
 +        c = str[b];
 +        str[b] = str[i];
 +        str[i] = c;
 +        b++;
 +    }
 +    return len;
 +}
 +
 +/* EOF */
 +</​code>​
 +===tools.h===
 +
 +<code C tools.h>
 +/* $Id$ */
 +
 +#define MAX_LINE_LEN 1024
 +
 +uint16_t str_len(uint8_t * str);
 +uint8_t * str_trim(uint8_t * str, uint8_t c);
 +
 +int32_t int_power(uint8_t n, uint8_t s);
 +int32_t str_geti(uint8_t * str);
 +uint8_t int_gets(int32_t num, uint8_t *str, uint8_t str_len, int16_t base);
 +
 +/* EOF */
 +
 +</​code>​