vimwiki/tech/ATMega328P.wiki

327 lines
14 KiB
Plaintext
Raw Normal View History

2021-11-13 05:51:32 +00:00
= Arduino Nano/ATMega328P =
2021-09-23 17:54:24 +00:00
A very small arduino product, better for hobby embedding
see [[arduino_techniques|Programming Techniques]]
2021-11-13 05:51:32 +00:00
See datasheet https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
2021-09-23 17:54:24 +00:00
== Features ==
* ATMEL AVR ATmega328P microcontroller
* 8 bit @16Mhz
* 2Kbytes SRAM
* 32Kbytes flash
* 1Kbytes EEPROM
2021-10-11 03:22:53 +00:00
* Three on board LED's * 20 IO pins
2021-09-23 17:54:24 +00:00
* 6 PWM and 6 ADC
== Notes ==
2021-10-11 03:22:53 +00:00
* WHEN UPLOADING BE SURE TO SET BOARD TO ATMEGA328OLD
- this is the atmega328old for BOARD_SUB in the makefile
2021-09-23 17:54:24 +00:00
=== Memory ===
* AVR instructions are 16 or 32bits wide, therefore the flash is 16K x 16
* EEPROM has endurance of ~10000 write cycles
* Program counter is 14 bits wide
* First 32 memory locations (0x0000 - 0x001F) are registers
* Next 64 registers are standard IO (0x0020 - 0x005F)
* Next 160 are extended IO (0x0060 - 0x00FF)
* Everything else is SRAM (0x0100 - 0x08FF)
=== IO ===
* GPIO pins
* Have a Data Direction Register (DDR)
- Sets if data should go in or out
* Is kept up via a [[multiplexer]] to decide which bit
=== Pins ===
2021-11-03 21:45:01 +00:00
The ATMega328P can control all of its pins via the use of an abstraction,
called ports. Each port has registers associated to it, and each pin
corresponds to a bit in a port register.
Port D controls pins D0 - 7,
Port C controls the analog Pins,
Port B controls pins D8 - 13
Each port has 3 registers associated with it. Port* is the register that allows
2021-11-03 22:00:01 +00:00
writing to the pins. These are PortB (0x25), PortC (0x28), and PortD (0x2B).
The Data Direction Registers (DDR*) determine if the Pin is used for Input or
Output. When a bit is set to zero (0), the pin will be used for input. Setting
a pin to one (1) will enable it for output. The three DDR* registers are DDRB,
(0x24), DDRC (0x27), and DDRD (0x2A). Finally, there are the PIN* registers,
which allow for input to taken. These registers are read only. The three PIN*
registers are PINB (0x23), PINC (0x26), and PIND (0x29).
2021-11-03 21:45:01 +00:00
2021-11-03 22:45:01 +00:00
To help with reading, the above info is in this table.
| Port | DDR | Port | Pin |
---------------------------
| B | 0x24 | 0x25 | 0x23 |
| C | 0x27 | 0x28 | 0x26 |
| D | 0x2A | 0x2B | 0x29 |
2021-10-11 03:22:53 +00:00
=== Interrupts ===
Interrupts are the same as OS typical interrupts, controlled by the Interrupt
2021-11-04 20:00:01 +00:00
lookup table. On this device the ILT is instead a control [[registers]]. The
code an interrupt calls is called an Interrupt Service Routine (ISR).
2021-10-11 03:22:53 +00:00
2021-11-03 18:55:21 +00:00
The External Interrupt Control Regsiter (EICR 0x69) is a register that allows you to set
the behaviour of the two built in interrupts. The Behaviour is set via setting
two bits. Bits 3-2 are for Interrupt 1 on pin D3, and Bits 1-0 are for
Interrupt 0 on pin D2. Below is a table of the values and their behaviour
| Bits | Description |
----------------------
| 00 | Low level makes an interrupt |
| 01 | Any logical change makes an interrupt |
| 10 | Falling edge makes an interrupt |
| 11 | Rising edge makes an interrupt |
To enable the interrupt, you must write a one (1) to the appropriate bit in the
External Interrupt Mask Register (EIMSK 0x3D). Bit 0 set INT0, and Bit 1 sets
INT1.
NOTE external activity on the pin, once the EIMSK bit is set, will cause an
interrupt even if the pin is set as an output pin.
Once an interrupt is triggered, the External Interrupt Flag Register (EIFR
0x3C) will have a one (1) written to the corresponding bit for that interrupt.
The flag is set automatically, and cleared once the interrupt has concluded.
The flag can be cleared by writing to it manually. Bit0 controlls INT0 and Bit
1 controlls INT1.
2021-11-03 16:45:01 +00:00
2021-11-03 19:00:01 +00:00
Finally, for interrupts to be enabled at all, a one (1) must be written to the
Status Register (SREG 0x5F). Bit 7 is the global interrupt enable flag, and
must have a one (1) written to it in order for interrupts to occour, regardless
of the state of the EIMSK register.
2021-11-03 16:45:01 +00:00
2021-11-03 19:15:01 +00:00
To implement an interrupt in code, see the following C example
{{{
//enable the interrupts as explained above
ISR(INT0_vect){
//perform interrupt task
}
}}}
2021-11-03 16:45:01 +00:00
=== Clock ===
2021-11-03 18:45:01 +00:00
The ATMega328P has 3 timers, two 8bit timers and one 16bit timer. These timers
2021-11-03 19:15:01 +00:00
can be used for PWM for motors and the like.
2021-11-03 19:45:01 +00:00
The timers are controlled by the General Timer/Counter Control Register (GTCCR
0x43). Bit 7 is the Timer/Counter sync Mode (TSM) and when set, halts the
2021-11-03 20:00:02 +00:00
timers so that they do not increment during configuration. Once TSM has a zero
wirtten to it, the PSRASY and PSRSYNC bits (bits 1-0 in this register) are
cleared via hardware, and the timers start counting. Bit 0 is the Prescaler
reset, and will reset the Timer/Counter 0 and 1 prescalers when 1 is written to
it. It is important to not that *Timer/Counter1 and 0 share the same prescaler
and a reset of the prescaler will affect both*
2021-11-03 19:15:01 +00:00
The Timer Counter 1 Control Register A (TCCR1A 0x80) is the register for
controlling Timer/Counter 1, along with Timer Counter 1 Control Register B
(TCCR1B 0x81). The high sets of two bits (bits 7-6 and 5-4), control the
compare output mode for channel A and B respectivly. These are controlled with
2021-11-03 19:30:01 +00:00
2 bit combinations as shown below.
2021-11-03 21:15:01 +00:00
NOTE These settings only apply to normal mode, and are on TTCR1A
2021-11-03 19:15:01 +00:00
| Bits | Description |
----------------------
| 00 | Normal Port operation, Comp register disconnected |
| 01 | Toggle OC1A/OC1B on compare match |
| 10 | Clear OC1A/OC1B on compare match (set output low) |
| 11 | Set OC1A/OC1B on compare match (set output high) |
2021-11-03 19:30:01 +00:00
TCCRB1B also can change the behaviour of the clock. Bit 7 sets the Input
Capture Noise Canceler (ICNC1). This will eliminate noise on the pin, and
delay the input caputre by 4 clock cycles. Bit 6 is the Input Capture Edge
Select 1 (ICES1). (To write about).
The lower 3 bits (2-0) determine the clock source. The possible vlaues are
shown below.
2021-11-03 19:15:01 +00:00
2021-11-03 19:30:01 +00:00
| Bits | Description |
----------------------
| 000 | No clock source (off) |
| 001 | CLK I/O / 1 (no prescale) |
| 010 | / 8 Prescaler |
| 011 | / 64 Prescaler |
| 100 | / 256 Prescaler |
| 101 | / 1024 Prescaler |
| 110 | External Clock source on T1 (falling edge) |
| 111 | External Clock source on T1 (rising edge) |
NOTE T1 will trigger the clock even if the pin in configured as output.
2021-11-03 21:30:01 +00:00
The mode of the timer is set using the lower two bits (1-0) of TCCR1A and bits
4-3 of TCCR1B. The two bits in TCCR1A are known as Waveform Generation Mode 11
(WGM11) and WGM10 for bits 1 and 0 respectivily. Bits 4-3 on TCCR1B are known
as WGM13 and WGM12 respecitvly. When ordred WGM13 through WGM10, they create a
4 bit value. The corresponding values and the effects are shown below.
| Mode | Mode of operation | TOP | Update OCR1* at | TOV1 Flag set on |
-----------------------------------------------------------------------
| 0 | Normal | 0xFFFF | Immediate | MAX |
| 1 | PWM, phase correct, 8bit | 0x00FF | TOP | BOTTOM |
| 2 | PWM, phase correct, 9-bit | 0x01FF | TOP | BOTTOM |
| 3 | PWM, phase correct, 10-bit | 0x03FF | TOP | BOTTOM |
2021-11-03 21:45:01 +00:00
| 4 | Clear on compare match | OCR1A | Immediate | MAX |
2021-11-03 21:30:01 +00:00
| 5 | Fast PWM, 8bit | 0x00FF | BOTTOM | TOP |
| 6 | Fast PWM, 9bit | 0x01FF | BOTTOM | TOP |
| 7 | Fast PWM, 10bit | 0x03FF | BOTTOM | TOP |
| 8 | PWM, phase and frequency correct | ICR1 | BOTTOM | BOTTOM |
| 9 | PWM, phase and frequency correct | OCR1A | BOTTOM | BOTTOM |
| 10 | PWM, phase correct | ICR1 | TOP | BOTTOM |
| 11 | PWM, phase correct | OCR1A | TOP | BOTTOM |
| 12 | CTC | ICR1 | Immediate | MAX |
| 13 | RESERVED | | | |
| 14 | Fast PWM | ICR1 | BOTTOM | TOP |
| 15 | Fast PWM | OCR1A | BOTTOM | TOP |
2021-11-03 19:30:01 +00:00
While in normal mode the Timer/Counter 1 Register counts up (inremental) and no
counter clear is done. The counter will overflow when the max 16 bit value
(0xFFFF) is reached. The registers that contain the counter values are The
Timer/Counter 1 Register (TCNT1H:TCNT1L 0x85[15:8] and 0x84[7:0], together TCNT1).
The Output Compare Register 1 A (OCR1AH:OCR1AL 0x89[15:8] and 0x88[0:7], together OCR1A)
2021-11-03 21:00:01 +00:00
and Output Compare Register 1 B (OCR1BH:OCR1BL 0x8B[15:8] and 0x8A[0:7], together OCR1B)
2021-11-03 19:30:01 +00:00
contain 16 bit values are contantly compared to the TCNT1 register. A compare operation is
performed, and a match generates an interupt.
2021-11-03 18:45:01 +00:00
2021-11-03 19:45:01 +00:00
These Interrupts can be turned on/off using the Timer/Counter 1 Interrupt Mask
Register (TIMSK1 0x6F). This register acts similary to the EIMSK register. Bit
5 enables Timer/Counter1 Input capture Interrupt (ICIE1), and the corresponsing
interrupt is triggerd when the ICF1 flag in TIFR1 is set.
Bits 2-0 enable the interrupts for Matches with Output Compare B, A, and
overflow resepectivly. When Bit 2 is set, the corresponding interrupt is
triggered only when the OCF1B flags in TIFR1 is set. This same principle
applies for OCF1A in TIFR1 for Bit 1, and TOV1 in TIFR1 for Bit 0. For more
info on TIFR1, refer below.
THe Timer/Counter 1 Interrupt Flag Register (TIFR1 0x36) is the register that holds
flags when Counter 1 (TCNT1) reaches the values in OCR1A and OCR1B. Bit 5 is
set when The input capture set by WGM to be used as the TOP value. Bits 2-0 are
set when TCNT1 matches the value in OCR1B, OCR1A, when when TCNT1 overflows,
respectivly.
2021-11-03 21:15:01 +00:00
==== Prescaler ====
2021-11-03 20:15:01 +00:00
To make the clock useful, the following will be an example of how to use Timer
1 to delay a certain amount of time. You will need the following information
* CPU freq (16MHz)
* Max timer value (0xFFFF or 65536)
* Chosen Prescaler (See above for prescaler values)
Divide the CPU freq by the chosen prescaler. Then divide that result through
the desired freqency. Be sure that the value is smaller than the max timer
value. If it is to large, choose a larger prescaler. Then place this in the
OCR** Register and enable the desired interrupt.
2021-11-03 21:15:01 +00:00
To assist in finding the correct value, below are the values of the clock speed
(16Mhz) over the prescalers.
NOTE to help with calculations, 0xFFFF is 65536 and 0xFF is 256
| prescaler | value |
---------------------
| 8 | 2000000 |
| 64 | 250000 |
| 256 | 62500 |
| 1024 | 15625 |
2021-11-15 21:00:01 +00:00
=== Analog to Digital ===
The ATMega328P includes an [[ADC]] for reading analog inputs. The ADC, like
everything else, is controlled via several control registers.
The primary control register is the ADC Multiplexer Selection Register (ADMUX
0x7C). Bit 7 and 6 select the reference voltage for the ADC. Any updates to
this register do not take effect till after an ongoing ADC operations has
completed. The internal voltage reference may not be used if a voltage is
2021-11-16 17:00:01 +00:00
applied across the AREF pin (Pin 21 on the Nano). Below are valid values
for bits 7 and 6.
2021-11-15 21:00:01 +00:00
| Bits (7-6) | Description |
----------------------------
| 00 | AREF, internal reference voltage turned off |
| 01 | AV,,cc,,, with an external capactior on AREF |
| 10 | Reserved (non functioning) |
| 11 | Internal 1.1V reference used with capactior on AREF |
Bit 5 of ADMUX changes the presentation of the ADC result, and when set to one
(1) the value will be left adjusted, otherwise it will be right adjusted. This
2021-11-16 17:30:01 +00:00
change happens instantly, regardless of the actions in the ADC. This option is
called ADC Left Adjust Result (ADLAR).
2021-11-15 21:00:01 +00:00
Bits 3-0 set which ADC pin will be converted (NOTE these are the pins on PortC
on the Arduino Nano). For values 0 through 7 (binary values in bits 3-0), will
select the corresponding ADC pin. 0b1000 is a sepcial ADC, connected to the
internal temperture sensor. 0b1110 (10d14) is the internal reference voltage of
1.1V, and 0b1111 (10d15) is internal reference GND (0V). All non mentioned
values are not used
To control the ADC, the ADC control and Status Register A (ADCSRA 0x7A) and ADC
2021-11-15 21:15:01 +00:00
Control and Status Register B (ADCSRB 0x7B) are used. Bit 7 of ADCSRA (ADC
Enable or ADEN) enables the ADC when high (1), and disables when low.
2021-11-16 16:45:01 +00:00
Setting this bit low during a conversion will stop the conversion. Bit 6 of
2021-11-16 17:00:01 +00:00
ADCSRA (ADC Start Conversion or ADSC) will start the ADC. The first conversion
performed when enabling this (since ADEN was changed), will take 25 cycles
2021-11-16 19:00:01 +00:00
instead of 13, due to the init that must be done.
Bit 5 of ADCSRA enables auto triggering of the ADC. The conversion will
start on the positive edge of a trigger. See the trigger selection bits in ADCSRB.
Bit 4 is the interrupt flag for completed ADC conversions. To Enable this
interrupt, write a one to Bit 3, the ADC interrupt enable.
Bits 2-0 are the ADC prescaler bits. These determine the division factor
between the system clock and the input clock to the ADC. Valid values are
shown below.
2021-11-16 17:15:01 +00:00
| Bits (2-0) | Division Factor |
--------------------------------
2021-11-16 17:30:01 +00:00
| 000 | 2 |
| 001 | 2 |
| 010 | 4 |
| 011 | 8 |
| 100 | 16 |
| 101 | 32 |
| 110 | 64 |
| 111 | 128 |
ADCSRB is also used to control the ADC, and Bits 2-0 control the ADC auto
trigger source. All of these conversions occour on the rising edge of the
selected source. If ADEN in ADCSRA is set, then the corresponding interrupts
will be called. (NOTE: Free running mode, 0b000, generates no interrupts and
just continously converts input).
2021-11-16 17:45:01 +00:00
| Bits (2-0) | Trigger Source |
-------------------------------
| 000 | Free running mode (No interrupts) |
| 001 | Analog Comparator |
| 010 | External Interrupt 0 |
| 011 | Timer/Counter0 compare Match A |
| 100 | Timer/Counter0 overflow |
| 101 | Timer/Counter1 compare Match B |
| 110 | Timer/Counter1 overflow |
| 111 | Timer/Counter1 capture event |
2021-11-16 17:30:01 +00:00
The result of the ADC conversion is stored in the ADC Data Register (ADCH:ADCL
0x79[15:8] and 0x78[7:0]). When ADLAR of ADMUX is set low, Bit 9 of the ADC
data register is the most signifigant bit, and Bit 0 is the least. When ADLAR
is high, Bit 15 is the most signifigant, while Bit 6 is the least.
2021-11-16 17:45:01 +00:00
When running pins in analog mode, the digital input buffer on the pin can also
2021-11-16 18:45:01 +00:00
be disabled (this is ideal to save power). This is done by modifying the
Digital Input Disable Register 0 (DIDR0 0x7E). Bits 5-0 correspond to ADC5-0
pins (A5-A0 on the Nano). ADC7 and ADC6 do not have digital input pins, and
therefore do not need digital disable bits.