Archive for the ‘avr’ Category

ATMega88 basic board

26-12-2007

Small project in KiCad.
ATMega88 with power supply, isp and rs232 connectors on first schematic.
ATMega88 basic board
Here in png file.

Module with max232.
ATMega88 basic board
Here in png file.

It’s good idea to make separate, small module for rs232 communication – it may be useful in other projects. You should think about rs232 connector pinout (between board and module). In this case it is possible to plug P2 (RS232) inversely – this may burn up your rs232 module and even com port or supplier.

I haven’t got max232 for 3.3 V power supply so I usually put 5 V regulator on rs232 module. As far as I remember ATMega88 tolerates 5 V on its inputs even when it’s powered with 3.3 V.
To launch this board you’ll need also stk200 programmer, it’s very simple and easy to google.
On this basic board you may run uart example. Of course you need to configure clock speed (fuse bits + uart registers)…

ATMega88 basic board – KiCad project.
AVR ATMega88 – KiCad lib.

ISP quick tip

23-04-2007

Low frequency main clock…

If you use simple ISP programmer (like stk200) and your AVR microcontroller stops responding after changing clock frequency to very low – don’t panic.

I’ve got similar problem with avrdude – it just can’t detect atmega88 after I change clock speed to about 100kHz. Because I’m using the power save mode (those with timer2 clock enabled) changing the main clock prescaler gives me about 100-200 uA less current consumption. What I tried to do was to change system prescaler before the sleep mode (I’ve changed timer2 prescaler so timer worked with same speed in normal and sleep mode).

Avrdude can’t detect device because it’s to inpatient :-). All you have to do is talk to your AVR a bit slower. I’m afraid it can’t be done with avrdude (at least you probably may put some delays into avrdude code to make it work slower, avrdude is an open source utility, so use the source luke :-) ). Theoretically AtmelISP had some options to change frequency of programming avr with stk200, but I could’nt find any working with atmega88 and stk200 aplication on Atmel site.

Use uisp!

Uisp is an isp programmer, like avrdude. I’m not sure if uisp supports newer avr microcontrollers (I’m not so sure if “new” is the right word here) like atmega88, but I was able to erase flash memory with atmega8 parameter. After that avrdude starts detecting my atmega.

AVR, UART C++ example…

02-03-2007

Some people came here from Google, looking for “avr example”. I’m playing with Atmega88 for a few days, because I’m thinking about simple motorcycle alarm.

Normally when I get new microcontroller I’m programming UART to get some readable debug output. It (probably) won’t be needed in final version of device – I don’t want MAX232 to consume power and I may have not enough memory to append extra debug code. (situation with not enough memory would be a nightmare, but it’s still possible – UART and Debug classes aren’t very big, but const strings with debug output may consume a lot) Anyway it’s good idea to get UART working at the very beginning.

Of course you know that you may set your house on fire or brake your leg because of my ideas or software I developed. I’ve got both legs straight and they seem to be all right, but it doesn’t prove anything. I’ve heard that probability of train appearing over your head (3..2..1..now) doesn’t equal zero. So, you’ve been warned.

I’ve written a post about avr and interrupts in c++ about three weeks ago. There was an example of defining interrupt routine as a friend of class. I’ve implemented C_UART class methods and added C_Debug class.

You can get sources here.

Directories and files:

  • Devs
    • debug.h, debug.cpp – debug device, defines operator <<
    • devs.h, devs.cpp – devices namespace
  • Periphs
    • uart.h, uart.cpp – uart peripheral class and interrupt routines
    • periphs.h, periphs.cpp – peripherals namespace

After including files with namespaces in main.cpp:
Debug<<"Hello World!\n"<<"uiTest = "<<123<<"\n";

Remember that there is no memory copying, so there is no hidden buffers – when you’re using this debug output microcontroller waits until all data is sent.
You have to change UBRR0H/L definitions in uart.h. They’re correct for baud rate 9600 when clock is ~8.8MHz. You may find proper values in ATmega88 datasheet.

Makefile is based on some example from AVRFreaks, I’ve just modified it to compile C++ code, added some dependencies and run statement. You may compile this project using WinAVR under Windows or anyhow under Linux.

After “$ make all” and “$ make run” you should get something like this (terminal – 9600/8/1):

Hello World!
uiTest = 123

That’s all folks :-).

Thanks to Patrys for hosting my files.

AVR interrupts in C++

07-02-2007

AVR interrupts in C…
Defining interrupt handler function under gcc is quite simple. All you have to do is write your own function and name it with macro ISR(vector_name), enable interrupts and allow interrupt generation for selected peripheral. For example ISR for uart transmitter should look like this:


ISR(USART_TX_vect)
{
    Code sending next byte...
}

Such handler works in C and C++, it even might be sufficient. Anyway it’s not very friendly for object – oriented programming.

Interrupts and object-oriented programming…
Interrupt itself is kind of dysfunction in program processing. There are some methods to predict jump condition but processor can’t predict when will an interrupt occur. Every time interrupt occurs processor has to flush pipeline and jump to interrupt routine.
In C++ you can describe peripheral as a class, here is simple example for uart public interface:


class C_UART
{
public:
    /// Turning uart on, setting registers (baudrate...)
    void Init(void);
    /// Sending uiSize bytes of pBuffer.
    bool Send(char* pBuffer, unsigned int uiSize);
    /// Receiving uiSize bytes to pBuffer.
    bool Receive(char* pBuffer, unsigned int uiSize);
    /// Checking if uiSize of pBuffer is sent/received.
    bool IsTxReady(void)
    bool IsRxReady(void)
};

Such interface should be enough to send and receive sequence of bytes. In fact, because uart sends data byte after byte there has to be some data counters and local copies of pointers. They should be kept in private or protected area:


private:
    char* pTxBuffer;
    char* pRxBuffer;
    volatile unsigned int uiTxCounter;
    volatile unsigned int uiTxSize;
    volatile unsigned int uiRxCounter;
    volatile unsigned int uiRxSize;

Now it’s possible to check if uiTxCounter++ is equal to uiTxSize. If not – send next byte from pTxBuffer.
It’s what ISR should do, but it can operate on global/public variables only, it doesn’t have access to private members of objects.
First of all – I’m working with ATMega88, it has only one uart peripheral so I’ve added one static pointer to C_USART:


private:
    static C_UART* pUart;

Of course it’s possible to add static Create() method and use pUart as singleton, in this simple example it should be initiated in constructor of C_UART class (with this).
Also it could be an array of static pointers if there’s more then one instance of C_UART class (more then one uart peripheral so more interrupt sources also).
Because pUart is a static pointer so our uart object is now reachable, but it’s still inaccessible.
The definition of ISR(x) for USART_TX_vect macro looks like:


extern "C" void USART_TX_vect(void) __attribute__ ((signal));
void USART_RX_vect(void)

It’s not possible to make it class member, even static. But it’s possible to declare such function as a friend of C_UART class. Interrupt handler would be able to access static pUart and modify any of private members C_UART.
Here is my c_uart.h listing:


#ifndef _C_UART_H_
#define _C_UART_H_

extern "C" void USART_TX_vect(void) __attribute__ ((signal));
extern "C" void USART_RX_vect(void) __attribute__ ((signal));

class C_UART
{
private:
    char* pTxBuffer;
    char* pRxBuffer;
    volatile unsigned int uiTxCounter;
    volatile unsigned int uiTxSize;
    volatile unsigned int uiRxCounter;
    volatile unsigned int uiRxSize;
    static C_UART* pUart;
public:
    void Init(void);
    bool Send(char* pBuffer, unsigned int uiSize);
    bool Receive(char* pBuffer, unsigned int uiSize);
    bool IsTxReady(void);
    bool IsRxReady(void);
    C_UART();
    friend void USART_TX_vect(void);
    friend void USART_RX_vect(void);
};
#endif