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:
The microprocessor is very modest for 2017 but I liked simplicity (relative) of its programming.
# cu -s 38400 -l /dev/ttyU0 Connected ######################### ### UNIX7.ORG ############## READY>23 OK 23 READY>
# # $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
/* $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 */
/* $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 */
/* $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); } }
/* $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 */
/* $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 */