Monthly Archives: August 2013
AVR: avr-libc Internals
pgm_read_byte()
Abstract
The pgm_read_byte() is a macro that reads a byte of data stored in a specified address(PROGMEM area).
Source Code
The pgm_read_byte() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.
#define pgm_read_byte(address_short) pgm_read_byte_near(address_short)
The input is address_short and calls the pgm_read_byte_near() macro.
pgm_read_byte_near()
Abstract
The pgm_read_byte_near() is a macro that reads a byte of data stored in a specified address(PROGMEM area).
Source Code
The pgm_read_byte_near() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
The input is address_short and the macro converts the address_short to uint16_t, then calls __LPM() macro.
__LPM()
Abstract
The __LPM() is a macro that reads a byte of data stored in a specified address(PROGMEM area).
Source Code
The __LPM() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.
#define __LPM(addr) __LPM_enhanced__(addr)
The input is addr and just calls __LPM_enhanced__().
See Intrinsic Functions
__LPM_enhanced__()
Abstract
The __LPM_enhanced() is an assembler code that reads a byte of data stored in a specified address(PROGMEM area).
Source Code
The __LPM_enhanced() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.
#define __LPM_enhanced__(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ \
( \
"lpm %0, Z" "\n\t" \
: "=r" (__result) \
: "z" (__addr16) \
); \
__result; \
}))
or newer avr-libc
#define __LPM_classic__(addr) \
(__extension__({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ \
( \
"lpm" "\n\t" \
"mov %0, r0" "\n\t" \
: "=r" (__result) \
: "z" (__addr16) \
: "r0" \
); \
__result; \
}))
The lpm, short for Load Program Memory, is a instruction that reads a byte of data from PROGMEM area. It substitue a data at addr for __result, then returns the __result.
Sources:
pgm_read_byte() marco
pgm_read_byte_near() marco
__LPM() marco
__LPM_enhanced__() marco
Arduino: Understanding the Internals
/* pin = Arduino Mapped Pin Name, ex. Digital pin 22: pin = 22 */
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
SREG (Status Register) und Globale Interrupts aktivieren: SREG -Register
extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; #define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define pgm_read_byte(address_short) pgm_read_byte_near(address_short) #define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
Was pgm_read_byte() macht bzw. wie es in Assembler übersetzt wird: Source von pgm_read_byte
C:\arduino-1.0.4\hardware\tools\avr\avr\include C:\arduino-1.0.4\hardware\arduino\cores\arduino
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
&DDRA,
&DDRB,
&DDRC,
&DDRD,
&DDRE,
&DDRF,
&DDRG,
&DDRH,
NOT_A_PORT,
&DDRJ,
&DDRK,
&DDRL,
};
/arduino/variants/mega/pins_arduino.h
Accessing data past 64k boundary on atmega1280
Arduino: Flashing a standalone ATmega
Sensors
Gyroscope, Acceleration and Compass
| MPU-6050 | 3x Axis accelerometer sensor and 3x Axis gyroscope sensor |
| MPU-9150 | Nine-Axis (Gyro + Accelerometer + Compass) MEMS MotionTracking (MPU-6050 + AK8975) |
| AK8975 | 3-axis electronic compass |
| HMC5883L | Triple Axis Magnetometer |
| BMP180 | Barometric Pressure Sensor |
| L3GD20 | 3-axis digital gyroscope |
| LSM303D | 3D accelerometer and 3D magnetometer |
Humidity and Temperature
| TMP006 | Infrared Thermopile Sensor |
| AM2302 | humidity capacitor module |
| AM2321 | capacitive humidity sensing digital temperature and humidity sensor |
| SHT21 | 3-axis electronic compass |
| SHT11 | Triple Axis Magnetometer |
| SHT15 | Barometric Pressure Sensor |
AM2302 (wired DHT22) temperature-humidity sensor
Sensirion Temperature/Humidity Sensor – SHT11
Arduino – Temperatur und Luftfeuchtigkeit mit dem DHT22 prüfen.
Erfahrungen mit 1-Wire Temp/Feuchte-Sensor AM2305 (anderer Sensor)
Light
| ISL29023 | Integrated Digital Light Sensor with Interrupt |
AVR: 7-segment display
AVR: Binary to BCD and vice versa
unsigned int bcd2i(unsigned int bcd) {
unsigned int decimalMultiplier = 1;
unsigned int digit;
unsigned int i = 0;
while (bcd > 0) {
digit = bcd & 0xF;
i += digit * decimalMultiplier;
decimalMultiplier *= 10;
bcd >>= 4;
}
return i;
}
unsigned int i2bcd(unsigned int i) {
unsigned int binaryShift = 0;
unsigned int digit;
unsigned int bcd = 0;
while (i > 0) {
digit = i % 10;
bcd += (digit << binaryShift);
binaryShift += 4;
i /= 10;
}
return bcd;
}