Last active
August 29, 2015 14:01
-
-
Save electronut/3cbb45b7bd092fad1253 to your computer and use it in GitHub Desktop.
Various ATtiny84 hacks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//************************************************************ | |
// attiny84-hacks.c | |
// | |
// Various snippets of code that I have developed for | |
// the ATtiny84 | |
// | |
// Author: Mahesh Venkitachalam | |
// Website: electronut.in | |
//************************************************************ | |
//************************************************************ | |
// ADC auto conversion | |
// enable ADC | |
ADCSRA |= (1 << ADEN); | |
// enable auto conversion | |
ADCSRA |= (1 << ADATE); | |
// convert first value | |
ADCSRA |= (1 << ADSC); | |
while(1) { | |
unsigned char adcl = ADCL; | |
unsigned char adch = ADCH; | |
int result = (adch << 8) | adcl; | |
} | |
//************************************************************ | |
//************************************************************ | |
// ADC manual conversion | |
// start conversion | |
ADCSRA |= (1 << ADSC); | |
// loop till done | |
while(ADCSRA & (1 << ADSC)); | |
// use h/l regs | |
unsigned char adcl = ADCL; | |
unsigned char adch = ADCH; | |
int result = (adch << 8) | adcl; | |
// or use ADC | |
result = ADC; | |
//************************************************************ | |
//************************************************************ | |
// set up 8-bit timer to do something every 1 second | |
setup_timer() { | |
cli(); | |
// set prescaler to 1024 | |
TCCR0B |= (1 << CS02) | (1 << CS00); | |
// set overflow interrupt enable | |
TIMSK0 |= (1 << TOIE0); | |
sei(); | |
} | |
volatile int nTimer0 = 0; | |
ISR(TIM0_OVF_vect) | |
{ | |
// for clock running at 8000000 Hz with prescalar of 1024 | |
// 8-bit counter overflows = 8000000/1024/256 = 30.52 every second | |
if (nTimer0 == 31) { | |
// toggle PB1 | |
PORTB ^= (1 << PB2); | |
// reset | |
nTimer0 = 0; | |
} | |
// increment count | |
nTimer0++; | |
} | |
//************************************************************ | |
//************************************************************ | |
// serial communications: | |
// us an FTDI adapter and connect PB1 to Rx of adapter | |
#define F_CPU 8000000 | |
char pinTX = PB1; | |
volatile unsigned char currByte = 0; | |
volatile int sendingData = 0; | |
// initialize | |
void init_serial() | |
{ | |
// set TX pin as output | |
DDRB = (1 << pinTX); | |
// set up timer1: | |
cli(); | |
// 16 bit timer | |
// Divide by 1 | |
TCCR1B |= (1<<CS10); | |
// Count cycles - (1/9600)*8000000 | |
OCR1A = 833; | |
// Put Timer/Counter1 in CTC mode | |
TCCR1B |= 1<<WGM12; | |
// set interrupt flag | |
TIMSK1 |= 1<<OCIE1A; | |
sei(); | |
} | |
// send a byte | |
void send_byte(char data) | |
{ | |
// set flag | |
sendingData = 1; | |
// set current data byte | |
currByte = data; | |
// wait till done | |
while(sendingData); | |
} | |
// which bit was sent last? (0-10) | |
// -1 implies none sent | |
volatile char bitNum = -1; | |
// 16-bit timer CTC handler - Interrupt Service Routine | |
ISR(TIM1_COMPA_vect) | |
{ | |
// serial data sent as: | |
// | |
// 9600 8 N 1 | |
// | |
// start(low)-0-1-2-3-4-5-6-7-stop(high)-idle(high)-idle(high) | |
// 12 bits sent per packet | |
// idle => high | |
if(!sendingData) { | |
PORTB |= (1 << pinTX); | |
} | |
else { | |
if(bitNum < 0) { | |
// start bit - low | |
PORTB &= ~(1 << pinTX); | |
// set bit number | |
bitNum = 0; | |
} | |
else if(bitNum >= 8) { | |
// stop bit - high | |
PORTB |= (1 << pinTX); | |
// increment | |
bitNum++; | |
// send 2 idle - high - bits | |
// not necessary strictly speaking | |
if(bitNum == 10) { | |
// done | |
sendingData = 0; | |
// unset bit number | |
bitNum = -1; | |
} | |
} | |
else { | |
// data bits: | |
// bit num is in [0, 7] | |
// extract relevant bit from data | |
char dataBit = currByte & (1 << bitNum); | |
if(dataBit) { | |
PORTB |= (1 << pinTX); | |
} | |
else { | |
PORTB &= ~(1 << pinTX); | |
} | |
// update bit number | |
bitNum++; | |
} | |
} | |
} | |
// write null terminated string | |
void send_str(const char* str) | |
{ | |
int len = strlen(str); | |
int i; | |
for (i = 0; i < len; i++) { | |
send_byte(str[i]); | |
} | |
} | |
//************************************************************ | |
//************************************************************ | |
// software PWM | |
// LED at PA1 is dimmed via PWM | |
volatile unsigned char pwmValue = 0; | |
ISR(TIM0_OVF_vect) | |
{ | |
static unsigned char tCount = 255; | |
// overflowed from 255 to 0 | |
if(++tCount == 0) { | |
// turn all PortA pins off | |
PORTA = 0; | |
// turn on pin | |
if (pwmValue != 0) { | |
PORTA |= (1 << PA1); | |
} | |
} | |
else { | |
// turn off pin when count exceeds PWM value | |
if (tCount > pwmValue) { | |
PORTA &= ~(1 << PA1); | |
} | |
} | |
} | |
// in main() | |
int main (void) | |
{ | |
DDRA |= (1 << PA1); | |
// set up 8-bit timer | |
cli(); | |
// set no prescaler | |
TCCR0B |= (1 << CS00); | |
// set overflow interrupt enable | |
TIMSK0 |= (1 << TOIE0); | |
sei(); | |
// loop | |
int count = 0; | |
while (1) { | |
pwmValue++; | |
_delay_ms(20); | |
} | |
return 1; | |
} | |
//************************************************************ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment