Useful functions
- _BV(bit) : Converts a bit number into a byte value.
#define _BV(bit) (1 << (bit))
- bit_is_clear(sfr,bit) : Test whether bit
bit
in IO registersfr
is clear.
#define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
- bit_is_set(sfr,bit) : Test whether bit
bit
in IO registersfr
is set.
#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
- loop_until_bit_is_set(sfr,bit) : Wait until bit
bit
in IO registersfr
is set.
#define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit))
- loop_until_bit_is_clear(sfr,bit) : Wait until bit
bit
in IO registersfr
is clear.
#define loop_until_bit_is_clear(sfr, bit) do { } while (bit_is_set(sfr, bit))
- cbi(sfr, bit) : Clear bit
bit
in registersfr
.
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
- sbi(sfr, bit) : Set bit
bit
in registersfr
.
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
- _SFR_BYTE(sfr) : De-reference
sfr
: to get the contents of the addresssfr
.
#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) #define _SFR_WORD(sfr) _MMIO_WORD(_SFR_ADDR(sfr)) #define _SFR_DWORD(sfr) _MMIO_DWORD(_SFR_ADDR(sfr)) #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) #define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr)) #define _MMIO_DWORD(mem_addr) (*(volatile uint32_t *)(mem_addr))
ATMega328P Registers
Name | Address | Purpose |
---|---|---|
SREG | 0x5F | AVR Status Register |
PORTB | 0x25 | PORT B Data Register [PORTB7..0] |
DDRB | 0x24 | PORT B Data Direction Register [DDB7..0] |
PINB | 0x23 | PORT B Input Pins Address [PINB7..0] |
PORTC | 0x28 | PORT C Data Register [PORTC7..0] |
DDRC | 0x27 | PORT C Data Direction Register [DDC7..0] |
PINC | 0x26 | PORT C Input Pins Address [PINC7..0] |
PORTD | 0x2B | PORT D Data Register [PORTD7..0] |
DDRD | 0x2A | PORT D Data Direction Register [DDD7..0] |
PIND | 0x29 | PORT D Input Pins Address [PIND7..0] |
- Every PIN has 3 associated registers: PORT, DDR & PIN.
- DDR sets the direction: 1 sets the pin as output, 0 as input.
- If PORT is written as logic 1 when pin is configured as input, the pull-up resistor is activated.
- If pin is configured as output, then PORT = 1 sets the pin HIGH, 0 sets the pin LOW.
- Writing logic 1 to PIN toggles the value of PORT, independent of value of DDR.
- Independent of the value of DDR, the port pin can be read via PIN register.
- When reading back a software assigned pin value, a NOP instruction must be inserted.
Tri-state
At reset all PINs are tri-stated. What is tri-state? Wikipedia explains it as such: In digital electronics three-state, tri-state, or 3-state logic allows an output port to assume a high impedance state in addition to the 0 and 1 logic levels, effectively removing the output from the circuit.
This is achieved by setting DDR = 0 & PORT = 0. And so we have the following cases:
DDR | PORT | State |
---|---|---|
0 | 0 | tri-state (high impedance) – no pull-up |
0 | 1 | high impedance with pull-up |
1 | 0 | Output LOW |
1 | 1 | Output HIGH |
Datatypes
Type | Description | #Bytes |
---|---|---|
int8_t / uint8_t | signed / unsigned char | 8 |
int16_t / uint16_t | signed / unsigned int | 16 |
int32_t / uint32_t | signed / unsigned long int | 32 |
int64_t / uint64_t | signed / unsigned long long int | 64 |
(u)intptr_t ((u)int16_t) | pointer variables | 16 |
Dealing with Interrupts
- Clear interrupts: cli()
- Set interrupts: sei()
- Clear interrupts, then restore original state of interrupts
// Save original value from register uint8_t oldSREG = SREG; // Clear interrupts cli(); // Do any work // Restore original values SREG = oldSREG;
Interrupt Handling
ISR(vector,attributes): ISR introduces an interrupt handler function (interrupt service routine) that runs with global interrupts initially disabled by default with no attributes specified.
Attributes: ISR_BLOCK (same as when no attributes are specified), ISR_NOBLOCK (ISR runs with global interrupts initially enabled. The interrupt enable flag is activated by the compiler as early as possible within the ISR to ensure minimal processing delay for nested interrupts.),
List of vectors for ATMega328
/* Interrupt Vectors */ /* Interrupt Vector 0 is the reset vector. */ #define INT0_vect _VECTOR(1) /* External Interrupt Request 0 */ #define INT1_vect _VECTOR(2) /* External Interrupt Request 1 */ #define PCINT0_vect _VECTOR(3) /* Pin Change Interrupt Request 0 */ #define PCINT1_vect _VECTOR(4) /* Pin Change Interrupt Request 1 */ #define PCINT2_vect _VECTOR(5) /* Pin Change Interrupt Request 2 */ #define WDT_vect _VECTOR(6) /* Watchdog Time-out Interrupt */ #define TIMER2_COMPA_vect _VECTOR(7) /* Timer/Counter2 Compare Match A */ #define TIMER2_COMPB_vect _VECTOR(8) /* Timer/Counter2 Compare Match B */ #define TIMER2_OVF_vect _VECTOR(9) /* Timer/Counter2 Overflow */ #define TIMER1_CAPT_vect _VECTOR(10) /* Timer/Counter1 Capture Event */ #define TIMER1_COMPA_vect _VECTOR(11) /* Timer/Counter1 Compare Match A */ #define TIMER1_COMPB_vect _VECTOR(12) /* Timer/Counter1 Compare Match B */ #define TIMER1_OVF_vect _VECTOR(13) /* Timer/Counter1 Overflow */ #define TIMER0_COMPA_vect _VECTOR(14) /* TimerCounter0 Compare Match A */ #define TIMER0_COMPB_vect _VECTOR(15) /* TimerCounter0 Compare Match B */ #define TIMER0_OVF_vect _VECTOR(16) /* Timer/Couner0 Overflow */ #define SPI_STC_vect _VECTOR(17) /* SPI Serial Transfer Complete */ #define USART_RX_vect _VECTOR(18) /* USART Rx Complete */ #define USART_UDRE_vect _VECTOR(19) /* USART, Data Register Empty */ #define USART_TX_vect _VECTOR(20) /* USART Tx Complete */ #define ADC_vect _VECTOR(21) /* ADC Conversion Complete */ #define EE_READY_vect _VECTOR(22) /* EEPROM Ready */ #define ANALOG_COMP_vect _VECTOR(23) /* Analog Comparator */ #define TWI_vect _VECTOR(24) /* Two-wire Serial Interface */ #define SPM_READY_vect _VECTOR(25) /* Store Program Memory Read */
ATMega328P Clock & Timer Registers
Name | Purpose | Details |
---|---|---|
TCCR2A | Timer/Counter Control Register A – use to set CTC |
0: Normal Operation WGM21: CTC WGM20: PWM COM2[A:B][0:1]: Manage OC2A, OC2B |
TCCR2B | Timer/Counter Control Register B – use to set prescaler |
0: Timer stopped CS20: No prescaling CS21, CS22: Prescaling WGM22: PWM |
TCNT2 | Timer/Counter Register | Running counter |
OCR2A | Output Compare Register A | Continuously compared with counter value. CTC mode – can trigger interrupt. Generate waveform on OC2A pin. |
OCR2B | Output Compare Register B | |
TIMSK2 | Timer/Counter2 Interrupt Mask Register | TOIE2 – overflow interrupt is enabled. OCIE2A – Compare Match A interrupt. OCIE2B – Compare Match B interrupt. |
ATMega328P Pin Change Interrupt Registers
Name | Purpose | Details |
---|---|---|
PCICR | Pin Change Interrupt Control Register | PCIE0: enables for PCINT[7:0] PCIE1: enables for PCINT[14:8] PCIE2: enables for PCINT[23:16] |
PCMSK0 | Pin Change Mask Register 0 | PCINT[0:7] |
PCMSK1 | Pin Change Mask Register 0 | PCINT[8:14] |
PCMSK2 | Pin Change Mask Register 0 | PCINT[16:23] |
References & Credits
- AVR LibC Reference Manual
- Arduino Source Code
- ATmega328p Datasheet
Pingback: Registers, registers & registers… | Hobby Electronics