Der ATtiny ist nun über eine Serielle Schnittstelle mit dem PC verbunden. Vorerst sendet er nur Daten und kann keine empfangen, aber immerhin.
Da der ATtiny diese Schnittstelle nicht von sich aus unterstützt, musste ich sie ausprogrammieren. So sieht der komplette Sourcecode aus:
// serial 9600,N,8,1
// led on PB3, tx on PB4
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // clear bit
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // set bit
volatile uint8_t tx_work = 0; // work request
volatile uint8_t tx_index; // loop for on byte
volatile uint8_t tx_buffer; // bufffer to send
ISR(TIM0_COMPA_vect) { // interrupt service routine
if (tx_work) { // work has to be done
if (tx_index == 0) { // index = 0
cbi(PORTB, PB3); // send start bit
} else if (tx_index <=8) { // index = data
if (tx_buffer & 1) { // from lsb to msb
sbi(PORTB, PB3); // send data bit
} else {
cbi(PORTB, PB3); // send data bit
}
tx_buffer >>= 1; // remove lsb
} else if (tx_index >= 9) { // index = 9
sbi(PORTB, PB3); // send stop bit
tx_work = 0; // work done
}
tx_index++; // next index
}
}
void serial_putc(char c) {
while(tx_work); // wait if busy
tx_index = 0; // reset index
tx_buffer = c; // data to transmit
tx_work = 1; // isr has work
}
void serial_print(const char *str) {
uint8_t i;
for (i = 0; str[i]; i++) {
serial_putc(str[i]); // write each character
}
}
int main(void) {
sbi(DDRB, PB4); // set led pin as output
sbi(DDRB, PB3); // set tx as output
sbi(TCCR0A, WGM01); // CTC mode, clear timer on compare match
sbi(TCCR0B, CS01); // prescaler clk/8 -> 1 tic = 1us for 8mhz
OCR0A = 103; // set compare register A
// 103us from wormfood.net/avrbaudcalc.php
sbi(TIMSK, OCIE0A); // enable interrrupt for OCROA==TCNT0
sei(); // enable interrupts
uint8_t v; // init visual counter
for(v = 0;; v++) { // main loop
PORTB ^= 1<<PB4; // toggle led
serial_print("toggle\r\n"); // serial out
_delay_ms (200); // wait 200ms
}
};
Das LED leuchtet dadurch alle 400 ms – so sieht das Ergebnis auf dem PC aus:
toggle toggle ...
PS: Das Programm verbraucht 324 Bytes. Eine frühere Version welche elegant mit fdevopen(&serial_putc, 0) und printf gearbeitet hat, musste ich verwerfen: sie war mit 2’552 Bytes, also rund 60% des verfügbaren Speichers, viel zu gross.