Skip to content

Instantly share code, notes, and snippets.

@electronut
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save electronut/3cbb45b7bd092fad1253 to your computer and use it in GitHub Desktop.
Save electronut/3cbb45b7bd092fad1253 to your computer and use it in GitHub Desktop.
Various ATtiny84 hacks
//************************************************************
// 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