vimwiki/tech/ATMega328P.wiki

240 lines
10 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 |