1
\$\begingroup\$

I successful managed to make a software UART without using the USI module and its interrupts.

The AVR code examples on Atmel and avrfreaks just do not work in either simulation or a real device so I got some help and made this soft UART.

Using Proteus I can send messages and receive them on my terminal window on a PC, I can send a character '1' to the Proteus simulation and it turns on an LED pin fine.

When I program the ATTiny861 I can receive messages at 9600bps perfectly but the interrupt procedure never ever fires, it should fire once on startup and then wait while CPU is idle for bit change on PIN.

int main(int argc, char **argv)
{
    USICR   =  0;             // Disable USI.
    MCUCR  |= (0<<ISC00);   
    MCUCR  |= (0<<ISC01);   
    GIFR    =  (1<<PCIF);     // Clear pin change interrupt flag.
    DDRA    = 0xFE;
    PORTA  |= (1<<PA0);       //int. Pull-up an  PA1
    PINA    = 0x00;
    PCMSK0 |= (1<<PCINT0);
    GIMSK  |= (1<<PCIE0);

    CLKPR = (1 << CLKPCE);
    CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);

    MCUCR = (1<<SE) | (0<<SM1) | (0<<SM0);   // Enable Sleepmode: Idle

    while(1){
      //send some startup messages ..

      sei();
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sleep_mode();  
    }
}

ISR(PCINT_vect) // interrupt for change in porta0 
{
    // pin change interrupt handler
    GIMSK &=  ~(1<<PCIE0);  
    if (!( PINA & (1<<PA0) ))  
    {
        static char chr;
        get_char(&serial_pins, serial_pin_in, &chr);
        RxData = chr;
    }    

    PCMSK0 |= (1<<PCINT0);  //  tell pin change mask to listen to pin0
    GIMSK  |= (1<<PCIE0);   // enable PCINT interrupt in the general interrupt mask of the porta
    GIFR    = (1<<PCIF);    // Clear pin change interrupt flag.

    static char message[] PROGMEM = " INTERRUPTED MESSAGE ";
    put_flash_string(&serial_port, serial_pin_out, (PGM_P) message);
}

I have other libraries and code segments loaded and I know the put_flash_string function works fine. If i take out sleep_mode it will dump messages into the terminal, I can delay it and it also works. But for some unknown reason on my hardware ATTiny861 it just will not interrupt.

I have been looking at this code for two weeks now and I really need some help. Atmel as you might guess is just vague and not really helpful. I'm not sure what to check any more and why the Proteus simulation works and not my hardware.

\$\endgroup\$
  • \$\begingroup\$ Just a note - if you're using the USI modules it's not a software UART - it's a hardware one. \$\endgroup\$ – AngryEE Apr 26 '12 at 14:16
  • \$\begingroup\$ @AngryEE USICR = 0; // Disable USI. According to the data sheet this disabled the built in USI module and does not register any interrupts for it either, making any pins ascociated with it free for other use. Could this cause the ISR(PCINT_vect) to stop functioning though? \$\endgroup\$ – Piotr Kula Apr 26 '12 at 14:24
  • \$\begingroup\$ @AngryEE you're quite right, it's not a pure software UART because he's not continuously polling the pin - he's using pin change interrupt events and timers. It's somewhere in between... \$\endgroup\$ – vicatcu Apr 26 '12 at 14:38
  • \$\begingroup\$ Ah, either there was an edit or I misread the first time. I thought he said he made a software UART with the USI, not without. \$\endgroup\$ – AngryEE Apr 26 '12 at 14:45
1
\$\begingroup\$

It's not really possible to give you a definitive explanation of why your device "works" in simulation but not in hardware based on the information provided. I will offer some suggestions though.

  1. Did you know avr-gcc has built in support for sleep?
  2. There is a table on page 36 of the datasheet describing Wake-up Sources mapped per Sleep Mode. There is a caveat there for: "(1) for INT0 and INT1, only level interrupt." Follow that trail to page 51 which describes the Low Level interrupt:

Note that if a level triggered interrupt is used for wake-up from Power-down, the required level must be held long enough for the MCU to complete the wake-up to trigger the level interrupt. If the level disappears before the end of the Start-up Time, the MCU will still wake up, but no interrupt will be generated. The start-up time is defined by the SUT and CKSEL Fuses as described in “Clock System” on page 24.

The bit time at 9600 baud is about 100 microseconds. Depending on your clock speed and your clock fuse settings I wonder if you could be blowing this budget? Have you tried with lower baud rate settings (e.g. 300 baud)? Can you tell us how you are clocking the chip? If you're using an external crystal (and you probably should be for UART operation) then the start up time is at best 16000 clock cycles!

Aside: This is obviously not related to your problem, but a useful macro provided by avrlibc is _BV(x) which can be used instead of (1 << x)

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I was not aware of the start up time issues i will research into that more. I set my clock fuse to internal 8mhz and I also have a 20mhz crystal-using anything else results in garbage. The bit time is 104ms exact each time as per my oscillation reading and receiving messages is perfect each time. I read not to use_BV because its non standard. Thanks for the answer! \$\endgroup\$ – Piotr Kula Apr 26 '12 at 14:39
  • \$\begingroup\$ @ppumkin _BV is the standard idiom for avrlibc, I'd be cautious about using the internal clock as I believe its only accurate to 10% (see table 19-2 on page 189) which is not "good enough" for UART operation. \$\endgroup\$ – vicatcu Apr 26 '12 at 14:46
  • \$\begingroup\$ Yes I know about the internal clock- but i could not get it to work with anything else though. \$\endgroup\$ – Piotr Kula Apr 26 '12 at 14:50
  • \$\begingroup\$ Thanks for your answer- I just wanted to ask you if you know a site with some examples for avrstudio. Atmel seem to have allot of IAR projects. Thanks Again \$\endgroup\$ – Piotr Kula Apr 26 '12 at 15:39
  • 1
    \$\begingroup\$ @ppumkin I'm pretty sure that AVR Studio uses AVR-GCC (and AVRLibc by extension) under the covers... perhaps this video will help you youtube.com/watch?v=plJf0r7IcWc \$\endgroup\$ – vicatcu Apr 26 '12 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.