simple arduino code without using avr headers in avr-libc - c

I have this simple code
That I am trying to compile for arduino microcontroller and without using avr headers. I just defined all macros in my source program file
but my gcc-avr says
led.c:15:8: error: lvalue required as left operand of assignment
DDRB |= 0B100000; // PORTB5 1010
^
Now I can expect this error on some cpu that io area is not virtual memory space of this process but I am running my code on mocrocontroller that must have execution bit. how to get rid of this message and compile it and able to run on arduino
But the gcc-avr throws error that
#define F_CPU 16000000
#define BLINK_DELAY_MS 5000
#include <util/delay.h>
#define __SFR_OFFSET 0x20
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
#define DDRB _SFR_IO8(0x04)
#define PORTB _SFR_IO8(0x05)
int main (void)
{
// Arduino digital pin 13 (pin 5 of PORTB) for output
DDRB |= 0B100000; // PORTB5 1010
while(1) {
// turn LED on
PORTB |= 0B100000; // PORTB5
// _delay_ms(BLINK_DELAY_MS);
int x=0;
while(x<25)
{
x++;
}
x=0;
// turn LED off
PORTB &= ~ 0B100000; // PORTB5
//hello
while(x<25)
{
x++;
}
//_delay_ms(BLINK_DELAY_MS);
}
}

The problems are the macros, you are defining the register as an integer, not as an address to an integer.
DDRB expands to 0x04 + 0x20 so you end up with code like (0x04 + 0x20) |= 0B100000;. You should be able to fix this with a cast and then de-reference:
#define _SFR_IO8(io_addr) ( *(volatile uint8_t*) ((io_addr) + __SFR_OFFSET) )
For details see How to access a hardware register from firmware?
Please also note that macros starting with double underscore __ are reserved for the compiler, so we should never use that or we might end up with naming collisions.

Related

When programming my Atmega644 MCU. Why does PORTD |= 0b00100000 work, but not PORTD |= (PD5 <<1)?

I have been trying to understand why the line
PORTD |= 0b00100000;
works, but not
PORTD |= (PD5 <<1);
I have a LED attached to PD5 which only lights up for the first command.
Do I have to define what "PD5" is? I never had to do that on my Atmega328P, but now on the Atmega644 it does not work?
Here is the libraries that I include
#define F_CPU 1000000UL // 1MHz internal clock
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/interrupt.h>
#include "lcd.h"
Not sure if anything can cause troubles? Am I missing something very basic here?
PORTD |= (PD5 <<1);
PD5 is defined as the number 5. Left-shifting it by one bit gives you 10, which has no relation to the value you want.
1 << PD5, on the other hand, will give you the result of left-shifting 1 by 5 bits, which is equal to 0b00100000 -- exactly what you're after.
The assignments differ.
PORTD |= 0b00100000;
sets bit 5 of PORT D to 1
whereas
PORTD |= (PD5 <<1);
set bit 1 and 2 of PORTD to 1 (as PD5 == 5 and PD5 << 1 == 10 (0x0A) i.e. 1010 binary)
Define some macro to set the LED on or off to prevent having to set the 'bits' each time
#define LEDON PORTD |= 0b00100000
#define LEDOFF PORTD &= ~0b00100000
Example usage
if ( put_led_on )
LEDON;
else
LEDOFF;
Or thanks to your own research
PORTD |= (1<<PD5);
which will set bit 5 to 1

AVR ATMEGA328p BAUD Rate Error / No Serial Connection

I cannot get my serial connection running to test my AVR chip. I currently assume it is because of the F_CPU value, but I am not 100% sure. The manual error i defined for #error Systematischer Fehler der Baudrate größer 1% appears when loading the program onto the chip. I don't know where to start right now finding the error. The console of my serial terminal does not show any output when connecting.
I created a config file I load in initially:
configGlobal.h
#ifndef F_CPU
#warning "F_CPU not yet defined, and will be set to 1MHz"
#define F_CPU 1000000UL
#endif
USART.c
#include "configGlobal.h"
#include <avr/io.h>
#include "USART.h"
#define BAUD 9600UL
#define BAUDRATE ((F_CPU) / (BAUD * 8UL) - 1) // set baud rate value for UBRR
void initUSART(void) {
// Requires BAUD
UBRR0H = (BAUDRATE >> 8) // Shift regisgter right by 8 bits to get upper 8 bits
UBRR0L = BAUDRATE;
UCSR0A |= (1 << U2X0);
// Enable USART
UCSR0B = (1 << TXEN0) | (1 << RXEN0); // Activate TX RX
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits, 1 stop bit
}
main.c
#include "configGlobal.h"
#include <avr/io.h>
#include <util/delay.h>
#include "USART.h"
int main(void) {
char serialCharacter;
// --- INITS --- //
DDRB = 0xff;
// Set up LED for output
initUSART();
printString("Hello World!\r\n");
return 0;
}
OUTPUT OF AVRDUDE
AVR Development Stack
Get input main.c file...
In file included from main.c:1:0:
configGlobal.h:2:2: warning: #warning "F_CPU not yet defined, and will be set to 1MHz" [-Wcpp]
#warning "F_CPU not yet defined, and will be set to 1MHz"
^
In file included from USART.c:1:0:
configGlobal.h:2:2: warning: #warning "F_CPU not yet defined, and will be set to 1MHz" [-Wcpp]
#warning "F_CPU not yet defined, and will be set to 1MHz"
^
In file included from /usr/local/CrossPack-AVR-20131216/avr/include/avr/io.h:99:0,
from USART.c:2:
USART.c: In function 'initUSART':
USART.c:10:2: error: called object is not a function or function pointer
UBRR0L = BAUDRATE;
^
Convert elf file to hex...
Uploading data to microcontroller...
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: Expected signature for ATmega328 is 1E 95 14
Double check chip, or use -F to override this check.
avrdude done. Thank you.
The compiler error is due to a missing a ";" in USART.c (line 10).
If you are unsure about usable baudrates, you can check for baudrate compatibility at e.g. http://wormfood.net/avrbaudcalc.php
Please keep in mind that using the AVRs internal RC-oscillator as a clock source might lead to unstable UART, as the frequency is not exactly at 8MHz (or 1MHz with CKDIV8=1).
The bottom part of the avrdude-log suggests that the device settings are not correct. Are you sure that an ATmega328 is connect and not an ATmega328P?

Use #define to specify multiple paramaters [duplicate]

I want to be able to define a tuple which represents the arguments needed by other macros.
I think the best way to show what I want is to show an example:
#include <avr/io.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PB7
#define LED LED_PORT, LED_DDR, LED_PIN
#define OUTPUT(port, ddr, pin) ddr |= 1 << pin
void main(void) {
OUTPUT(LED);
}
I want OUTPUT(LED) to be then expanded into:
LED_DDR |= 1 << LED_PIN
The problem that I get is to do with the order of expansion, and results in the following error:
macro "OUTPUT" requires 3 arguments, but only 1 given
This is for use with an AVR project with custom built hardware where I have defined LED and other components with a respective LED_PORT LED_DDR and LED_PIN.
I then want to define more macros that can take this LED and use the appropriate arguments to map to the most succinct way possible.
Is this possible with the standard C-preprocessor?
You can add a level of indirection to the macro to achieve this:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)
During rescanning, spec is expanded before OUTPUT_I, so the OUTPUT_I macro sees three parameters.

#define a tuple in C

I want to be able to define a tuple which represents the arguments needed by other macros.
I think the best way to show what I want is to show an example:
#include <avr/io.h>
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PB7
#define LED LED_PORT, LED_DDR, LED_PIN
#define OUTPUT(port, ddr, pin) ddr |= 1 << pin
void main(void) {
OUTPUT(LED);
}
I want OUTPUT(LED) to be then expanded into:
LED_DDR |= 1 << LED_PIN
The problem that I get is to do with the order of expansion, and results in the following error:
macro "OUTPUT" requires 3 arguments, but only 1 given
This is for use with an AVR project with custom built hardware where I have defined LED and other components with a respective LED_PORT LED_DDR and LED_PIN.
I then want to define more macros that can take this LED and use the appropriate arguments to map to the most succinct way possible.
Is this possible with the standard C-preprocessor?
You can add a level of indirection to the macro to achieve this:
#define OUTPUT_I(port, ddr, pin) ddr |= 1 << pin
#define OUTPUT(spec) OUTPUT_I(spec)
During rescanning, spec is expanded before OUTPUT_I, so the OUTPUT_I macro sees three parameters.

AVR clean pin aliasing solution - enumerating I/O bits

I'm working in C on an Arduino device, where the pins are labeled differently. I'm using PLAIN C though, not the Arduino "language".
Each pin is defined by it's port (eg. PORTB) and pin (bit) in the port (eg. PB0).
I'd like to concisely alias pins, so I could make macros or functions somewhat like what the Arduino uses:
pin_direction(D2, 1); // D2 as output
set_pin(D2, 0); // write zero to D2
pin_direction(D3, 0); // D3 as input
enable_pullup(D3, 1); // enable D3 pullup
Instead (atm) I have to use something ugly like this:
#define D0 0
#define D1 1
#define D2 2
#define D3 3
...
#define D10 2
#define D11 3
#define PORT_D0 PORTD
#define PORT_D1 PORTD
#define PORT_D2 PORTD
#define PORT_D3 PORTD
...
#define PORT_D10 PORTB
#define PORT_D11 PORTB
// the same for PIN_xx and DDR_xx
And then I can use macros to do the work:
#define sbi(port, bit) (port) |= _BV(bit)
#define cbi(port, bit) (port) &= ~ _BV(bit)
sbi(DDR_D2, D2); // D2 to output
cbi(PORT_D2, D2); // D2 to output
sbi(DDR_D3, D3); // D3 as input
sbi(PORT_D3, D3); // D3 pullup enable
Now this works, but it's very messy. Any idea how to - without a monster overhead of something like huge switch - do this better - more like my first example? Somehow enumerate all bits and then resolve the right register on the fly?
I'm using avr-gcc with avr-libc.
You can define macros which expand to multiple tokens, e.g.
#define PIN_D0 PORTD, 0
#define PIN_D1 PORTD, 1
...
#define PIN_D10 PORTB, 2
Then use them in macros such as:
sbi(PIN_D0); // expands to sbi(PORTD, 0)
Some utility macros that may be useful with these macros are:
#define PORT_OF(port, bit) port
#define BIT_OF(port, bit) bit
which can be used in contexts such as:
PORT_OF(PIN_D10) // expands to PORTB
BIT_OF(PIN_D10) // expands to 2
Here's the solution I use.
In my util.h (common to all my AVR projects):
#define DDR_REG(port) DDR ## port
#define PORT_REG(port) PORT ## port
#define PIN_REG(port) PIN ## port
#define SET_BIT(port, bit) do { (port) |= (1 << (bit)); } while(0)
#define CLR_BIT(port, bit) do { (port) &= ~(1 << (bit)); } while(0)
#define BIT_IS_SET(port, bit) ((((uint8_t)(port)) >> ((uint8_t)(bit))) & 0x1)
#define IO_SET_INPUT_AUX(port, bit) CLR_BIT(DDR_REG(port), bit)
#define IO_SET_AS_INPUT(io) IO_SET_INPUT_AUX(io)
#define IO_SET_OUTPUT_AUX(port, bit) SET_BIT(DDR_REG(port), bit)
#define IO_SET_AS_OUTPUT(io) IO_SET_OUTPUT_AUX(io)
#define IO_OUTPUT_0_AUX(port, bit) CLR_BIT(PORT_REG(port), bit)
#define IO_OUTPUT_0(io) IO_OUTPUT_0_AUX(io)
#define IO_OUTPUT_1_AUX(port, bit) SET_BIT(PORT_REG(port), bit)
#define IO_OUTPUT_1(io) IO_OUTPUT_1_AUX(io)
#define IO_GET_INPUT_AUX(port, bit) BIT_IS_SET(PIN_REG(port), bit)
#define IO_GET_INPUT(io) IO_GET_INPUT_AUX(io)
In my pin mappings file:
#define UPBTN_IO B,7
#define DOWNBTN_IO D,0
#define ENTERBTN_IO D,1
(etc)
In code:
IO_SET_AS_INPUT(UPBTN_IO);
This relies on some fun preprocessor bits, like there only being one round of macro expansion on macro parameters.

Resources