; ; hello.serial.45.asm ; ; 9600 baud serial hello-world program ; ; Neil Gershenfeld ; CBA MIT 7/27/07 ; ; (c) Massachusetts Institute of Technology 2007 ; Permission granted for experimental and personal use; ; license for commercial sale available from MIT. ; .include "tn45def.inc" .equ tx_pin = PB2; transmit pin .equ led_pin = PB1; LED pin .equ button_pin = PB3; button input (normally low, high on press) .def bit_count = R16; bit counter .def temp = R17; temporary storage .def temp1 = R18; temporary storage .def txbyte = R19; data byte ; ; print ; .macro print ldi zl,low(@0*2) ldi zh,high(@0*2) rcall print_db .endmacro .cseg .org 0 rjmp reset ; ; bit delay ; serial bit delay ; .equ b = 13 ; 9600 baud (clock /8) ;.equ b = 8 ; 115200 baud (clock /1) bit_delay: ldi temp, b bitloop: dec temp brne bitloop ret ; ; putchar ; assumes no line driver (doesn't invert bits) ; .equ sb = 1; number of stop bits putchar: ldi bit_count, 9+sb; 1+8+sb com txbyte; invert everything sec; set start bit putchar0: brcc putchar1; if carry set sbi PORTB, tx_pin; send a '0' rjmp putchar2; else putchar1: cbi PORTB, tx_pin ; send a '1' nop ; even out timing putchar2: rcall bit_delay; one bit delay rcall bit_delay lsr txbyte; get next bit dec bit_count; if not all bits sent brne putchar0; send next bit ret; ; ; print_db ; prints a null-terminated .db string ; print_db: print_loop: lpm mov txbyte,R0 cpi txbyte,0 breq return rcall putchar adiw zl, 1 rjmp print_loop return: ret ; ; main program ; reset: ; ; set clock divider to /1 ; ;ldi temp, (1 << CLKPCE) ;ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0) ;out CLKPR, temp ;out CLKPR, temp1 ; ; set stack pointer to top of RAM ; ldi temp, high(RAMEND) out SPH, temp ldi temp, low(RAMEND) out SPL, temp ; ; LED and button initialization ; sbi DDRB, led_pin; send for LED sbi PORTB, led_pin; High off, low on cbi DDRB, button_pin ; activate pull-up: 0 for DDxn, 1 for PORTxn sbi PORTB, button_pin ; ; ; init comm pin for output ; sbi PORTB, tx_pin sbi DDRB, tx_pin ; ; Main loop ; loop: sbis PINB, button_pin ; clear pin means button pressed. if clear: rcall print_and_shine sbic PINB, button_pin ; else if set: rcall light_off rjmp loop print_and_shine: rcall light_on rcall print_message rcall delay rcall light_off rcall delay ret light_on: cbi PORTB, led_pin ret light_off: sbi PORTB, led_pin ret print_message: print message message: .db "Hello World!",1,0 ret delay: ldi temp, 255 delay_loop1: ldi temp1, 255 delay_loop2: dec temp1 brne delay_loop2 dec temp brne delay_loop1 ret