{"id":22202,"date":"2024-10-09T21:10:06","date_gmt":"2024-10-09T21:10:06","guid":{"rendered":"https:\/\/wolles-elektronikkiste.de\/?p=22202"},"modified":"2024-12-01T17:15:04","modified_gmt":"2024-12-01T17:15:04","slug":"programming-the-tinyavr-series-0-1-2-part-1","status":"publish","type":"post","link":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1","title":{"rendered":"Programming the tinyAVR series 0, 1, 2 &#8211; Part 1"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">About this Post<\/h2>\n\n<p>In my article <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/using-megatinycore\" target=\"_blank\" rel=\"noopener\">Using megaTinyCore<\/a> I showed how to upload sketches to the ATtiny microcontrollers of the tinyAVR \u00ae series 0, 1 and 2 using the <a href=\"https:\/\/github.com\/SpenceKonde\/megaTinyCore\" target=\"_blank\" rel=\"noopener\">board package from Spence Konde<\/a>. In the next two posts, I will go into programming at register level. This will be relevant if, for example, you want to use the timers of the tinyAVR microcontrollers or special functions such as the Event System or the Configurable Customer Logic (CCL).  <\/p>\r\n<p>I have already given an overview of the tinyAVR family and its technical features <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/using-megatinycore#megaTinyCore_family\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\r\n<p>The data sheets of the tinyAVR microcontrollers have several hundred pages. Of course, I can&#8217;t cover all of that in this article. I won&#8217;t cover functions that you can also conveniently control via the Arduino language (Wire, SPI, etc.). But I also had to limit myself thematically. So it&#8217;s definitely worth taking a look at the data sheet!    &nbsp;<\/p>\r\n<p>Here&#8217;s what you can expect in this post and its sequels:<\/p>\r\n<ul>\r\n<li><a href=\"#reg_programming_tinyavr\">Register programming of the tinyAVR series<\/a><\/li>\r\n<li><a href=\"#portx_module\">I\/O Control &#8211; PORTx Module<\/a><\/li>\r\n<li><a href=\"#portmux_module\">Reassigning Inputs \/ Outputs &#8211; PORTMUX Module<\/a><\/li>\r\n<li><a href=\"#evsys_module\">The Event System &#8211; EVSYS Module<\/a><\/li>\r\n<li><a href=\"#rtc_module\">Real-Time Counter &#8211; RTC Module<\/a><\/li>\r\n<li><a href=\"#wdt_module\">Watchdog Timer &#8211; WDT Module<\/a><\/li>\r\n<li><a href=\"#adc_module\">A\/D Converter &#8211; ADCn Module<\/a><\/li>\r\n\r\n\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#timer_a\" target=\"_blank\" rel=\"noopener\">Timer A &#8211; TCAn Module (Part 2)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#timer_b\" target=\"_blank\" rel=\"noopener\">Timer B &#8211; TCBn Module (Part 2)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#ccl_module\" target=\"_blank\" rel=\"noopener\">Configurable Custom Logic &#8211; CCL Module (Part 2)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#slpctrl_module\" target=\"_blank\" rel=\"noopener\">The tinyAVR MCUs go to sleep &#8211; SLPCTRL Module (Part 2)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-3-timer-d\" target=\"_blank\" rel=\"noopener\">Timer D &#8211; TCDn Module (Part 3)<\/a><\/li>\r\n<\/ul>\r\n\n<h4 class=\"wp-block-heading\">Serial output<\/h4>\n\n<p>And one more note in advance: in some sketches, I use <code>Serial.print()<\/code>. To get an output on the serial monitor, use a USB-to-TTL adapter and connect RX to TX, TX to RX and GND to GND. Don&#8217;t forget to set the port. If you are not uploading the sketches via UPDI, but already using the bootloader and USB-to-TTL adapter, then the serial output will work anyway.   <\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"reg_programming_tinyavr\">Register programming of the tinyAVR series<\/h2>\n\n<p>I will now try to explain the basic principles of register programming for the tinyAVR series briefly. For detailed information, please refer to the application note <a href=\"https:\/\/ww1.microchip.com\/downloads\/en\/Appnotes\/AVR1000b-Getting-Started-Writing-C-Code-for-AVR-DS90003262B.pdf\" target=\"_blank\" rel=\"noopener\">TB3262<\/a> from Microchip.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Everything is a little different<\/h3>\n\n<p>The following blink sketch for pin PA2 gives a first impression:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"blink.ino\" data-enlighter-title=\"blink.ino\">void setup() {\r\n    PORTA.DIRSET = PIN2_bm; \/\/ set PA2 (selectively!) to OUTPUT\r\n}\r\n   \r\nvoid loop() {\r\n    PORTA.OUTSET = PIN2_bm;  \/\/ set PA2 to HIGH \r\n    delay(200);\r\n    PORTA.OUTCLR = PIN2_bm;  \/\/ set PA2 to LOW\r\n    delay(200);\r\n}<\/pre>\r\n\n<p>This is very different from coding \u00e0 la <code>PORTA |= (1&lt;&lt;PA2)<\/code> that you are probably more familiar with.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Register<\/h4>\n\n<p>The registers are organized in modules. The modules are structures (data type struct), which is why you can see the dot notation in the blink sketch.  The name of the structure is the module, the registers are elements of this structure, e.g.<\/p>\r\n<ul>\r\n<li>PORTA.DIRSET:\r\n<ul>\r\n<li>Module: PORTA<\/li>\r\n<li>Register: DIRSET<\/li>\r\n<\/ul>\r\n<\/li>\r\n<\/ul>\r\n\n<h4 class=\"wp-block-heading\">Bit Masks and Bit Group Configuration Masks<\/h4>\n\n<p>To understand bit masks and bit group configuration masks, let&#8217;s take a look at the Control A Register (CTRLA) of timer B0 as an example. The module is called TCB. However, as some tinyAVR microcontrollers have two timers B (0 and 1), the number is appended to the module name. In general terms: &#8220;MODULNAME<strong>n<\/strong>.REGISTERNAME&#8221;. The CTRLA register of timer B0 is therefore called: TCB0.CTRLA.  <\/p>\r\n<p>The TCBn.CTRLA registers have various bits and the CLKSEL (Clock Select) bit group:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/09\/red_tcb_ctrla-1-1024x281.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"281\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/09\/red_tcb_ctrla-1-1024x281.png\" alt=\"TCBn.CTRLA register of the tinyAVR series\" class=\"wp-image-22084\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/09\/red_tcb_ctrla-1-1024x281.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/09\/red_tcb_ctrla-1-300x82.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/09\/red_tcb_ctrla-1-768x211.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/09\/red_tcb_ctrla-1.png 1234w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCBn.CTRLA register<\/figcaption><\/figure>\n\n<p>Bit masks are used to set single bits. Their names are formed according to the following scheme:<\/p>\r\n<ul>\r\n<li><strong>MODUL_BIT_bm<\/strong><\/li>\r\n<\/ul>\r\n<p>The module number is omitted from the bit mask. This is, for example, how you set the ENABLE bit for the timer B0: <\/p>\r\n<p><code>TCB0.CTRLA |= TCB_ENABLE_bm;<\/code><\/p>\r\n<p>The bit group configuration masks are used for bit groups (also known as bit fields), the names of which are formed as follows:<\/p>\r\n<ul>\r\n<li><strong>MODUL_BITGRUPPE_CONFIGURATION_gc<\/strong><\/li>\r\n<\/ul>\r\n<p>As an example, we specify that timer B0 uses the TCA clock:<\/p>\r\n<p><code>TCB0.CTRLA |= TCB_CLKSEL_TCA0_gc;<\/code><\/p>\r\n\n<p>CLKTCA corresponds to the CLKSEL value 0x2 or 0b10. In the register, CLKSEL is located at bit position 1 and 2, i.e. it is shifted 1 bit to the left. This is why the value of TCB_CLKSEL_TCA0_gc is 0x4 or 0b100.<\/p>\r\n<p>If you want to mask the bit group TCB_CLKSEL, you can use the bit group mask. Here in the general form:<\/p>\r\n<ul>\r\n<li><strong>MODUL_BITGRUPPE_gm<\/strong><\/li>\r\n<\/ul>\r\n<p>The value of TCB_CLKSEL_gm is 0x6 or 0b110, as you can easily check with <code>Serial.println(TCB_CLKSEL_gm, BIN)<\/code>.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Bit Positions and Bit Group Positions<\/h4>\n\n<p>Then there are the Bit Positions and the Bit Group Positions:<\/p>\r\n<ul>\r\n<li><strong>MODUL_BIT_bp<\/strong><\/li>\r\n<li><strong>MODUL_BITGRUPPE_gp<\/strong><\/li>\r\n<\/ul>\r\n<p>Unsurprisingly, they indicate the position of the bit or bit group in the register. So if you want to determine the current CLKSEL value of timer TCB0, you could do it like this:<\/p>\r\n<p><code>Serial.println( ((TCB0.CTRLA &amp; TCB_CLKSEL_gm) &gt;&gt; TCB_CLKSEL_gp) );<\/code><\/p>\r\n\n<p>It may all sound a little complicated at first, but you soon get used to this type of notation. It involves a certain amount of writing, but it pays off because the code is still easy to understand even after a few months.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Orientation in the Data Sheet <\/h4>\n\n<p>This way of programming registers takes some getting used to at first. What helps with orientation is the data sheet of the tinyAVR MCU in question. It is organized according to the modules and for each module there is a &#8220;Register Summary&#8221; with links to the individual registers, where you can then find the bit masks and bit group masks.   <\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/reg_summary_portx-1.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1011\" height=\"464\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/reg_summary_portx-1.webp\" alt=\"tinyAVR PORTx Register Summary\" class=\"wp-image-19472\" style=\"width:659px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/reg_summary_portx-1.webp 1011w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/reg_summary_portx-1-300x138.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/reg_summary_portx-1-768x352.webp 768w\" sizes=\"auto, (max-width: 1011px) 100vw, 1011px\" \/><\/a><figcaption class=\"wp-element-caption\">PORTx Register Summary (minor individual deviations possible)<\/figcaption><\/figure>\n\n<p>I also recommend looking at the &#8220;I\/O Multiplexing and Considerations&#8221; section of the data sheet. There you will find a table showing which pins have which functions. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Looking up the definitions<\/h4>\n\n<p>Sometimes (but rather rarely) the names for the bitmasks, bitgroups etc. in the data sheet are inconsistent with the names you have to use in the program. Fortunately, the compiler usually provides you with the correct alternative. <\/p>\r\n<p>Otherwise, you will find the definitions in the Arduino installation. Where exactly depends on your installation. For me, the directory is under:<\/p>\r\n<p>C:\\Users\\Ewald\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5\\avr\\include\\avr<\/p>\r\n<p>The files for the ATtinys have the designation iotn<em>xxx<\/em>.h. But even if you don&#8217;t have a problem, it is worth taking a look at this.<\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"portx_module\">I\/O Control &#8211; PORTx Module<\/h2>\n\n<h3 class=\"wp-block-heading\">PORTx Register <\/h3>\n\n<h4 class=\"wp-block-heading\">DIR, OUT and IN registers<\/h4>\n\n<p>As demonstrated by the register summary above, there are a number of registers whose names begin with &#8220;DIR&#8221; or &#8220;OUT&#8221;. The &#8220;DIR &#8230;&#8221; registers control which pins are used as INPUT or OUTPUT. With the help of the &#8220;OUT &#8230;&#8221; registers you set the pin level, i.e. HIGH or LOW. The second part of the name means:<\/p>\r\n<ul>\r\n<li>SET: sets bits in OUT and DIR \u2192 OUTPUT or HIGH<\/li>\r\n<li>CLR: clears bits in OUT and DIR \u2192 INPUT or LOW<\/li>\r\n<li>TGL: toggles the status.<\/li>\r\n<\/ul>\r\n<p>You can also write directly to the DIR and OUT registers, but the beauty of OUTSET, OUTCLR, OUTTGL and their DIR counterparts is that the instructions are pin-selective. Example:<\/p>\r\n<ul>\r\n<li><code>PORTx.OUT = PINy_bm;<\/code> sets pin y (with y = 0 to 7) of port x to HIGH and all other pins of port x to LOW. Here x = A, B or C, depending on which ports are available. <\/li>\r\n<li><code>PORTx.OUTSET = PINy_bm;<\/code> only acts on pin y, i.e. the statement corresponds to <code>PORTx.OUT |= PINy_bm;<\/code>.<\/li>\r\n<\/ul>\r\n<p>You can use the IN registers to read the status of the pins (<code>digitalRead()<\/code>, so to speak). However, if you write a bit to the PORTx.IN register, the corresponding bit is toggled in PORTx.OUT. The IN register is the counterpart to the PINx register of traditional AVR microcontrollers.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Control Register PINxCTRL <\/h4>\n\n<p>Each pin has its own control register, namely PINxCTRL:<\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_PORTx_PINx_CTRL-1024x82.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"82\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_PORTx_PINx_CTRL-1024x82.png\" alt=\"Arduino Nano Every \/ Nano 4808 Register - PORTn.PINxCTRL\" class=\"wp-image-19308\" style=\"width:840px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_PORTx_PINx_CTRL-1024x82.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_PORTx_PINx_CTRL-300x24.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_PORTx_PINx_CTRL-768x61.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_PORTx_PINx_CTRL.png 1239w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">PORTn.PINxCTRL Register<\/figcaption><\/figure>\n\n<p>The INVEN bit allows you to invert the INPUT and OUTPUT values. PULLUPEN activates the internal pull-up resistor. With ISC you can define the interrupt conditions or switch off the digital function of the pin completely (INPUT_DISABLE):<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/PINxCTRL_ISC_table.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"987\" height=\"310\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/PINxCTRL_ISC_table.webp\" alt=\"ISC[2:0] Bit Group Configurations\" class=\"wp-image-19306\" style=\"width:599px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/PINxCTRL_ISC_table.webp 987w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/PINxCTRL_ISC_table-300x94.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/PINxCTRL_ISC_table-768x241.webp 768w\" sizes=\"auto, (max-width: 987px) 100vw, 987px\" \/><\/a><figcaption class=\"wp-element-caption\">ISC[2:0] Bit Group Configuration<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\">Example Sketches for PORTx<\/h3>\n\n<h4 class=\"wp-block-heading\">Switching Pins<\/h4>\n\n<p>I&#8217;ll come back to the blink sketch and show that there are other ways to achieve the same effect:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"blink_sketch_alternatives.ino\" data-enlighter-title=\"blink_sketch_alternatives.ino\">void setup() {\r\n    PORTA.DIRSET = PIN2_bm; \/\/ set PA2 to OUTPUT\r\n    \/\/ PORTA.DIR |= (1&lt;&lt;2);\r\n    \/\/ PORTA.DIR |= (1&lt;&lt;PIN2_bp); \/\/ bp = bit position\r\n}\r\n\r\nvoid loop() {\r\n    PORTA.OUTSET = PIN2_bm;  \/\/ set PE2 to HIGH\r\n    \/\/ PORTA.OUT |= PIN2_bm;\r\n    delay(200);\r\n    PORTA.OUTCLR = PIN2_bm;\r\n    \/\/ PORTA.OUT &amp;= ~PIN2_bm; \r\n    delay(200);\r\n   \r\n    \/\/ Alternative: toggle pin:\r\n    \/\/ PORTA.OUTTGL = PIN2_bm;\r\n    \/\/ delay(200);  \r\n}<\/pre>\r\n\n<h4 class=\"wp-block-heading\">Reading Pin Levels <\/h4>\n\n<p>Here is an example of how you can read out individual pins. To do this, connect an LED to PA2 and a push-button, which emits a HIGH signal when pressed, to PA1. As long as you press the button, the LED lights up.  <\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"digital_read_from_port.ino\" data-enlighter-title=\"digital_read_from_port.ino\">void setup() {\r\n    PORTA.DIRSET = PIN2_bm; \/\/ PA1: OUTPUT\r\n    PORTA.DIRCLR = PIN1_bm; \/\/ PA2: INPUT\r\n}\r\n\r\nvoid loop(){\r\n    if(PORTA.IN &amp; PIN1_bm){\r\n        PORTA.OUTSET = PIN2_bm;\r\n    }\r\n    else{\r\n        PORTA.OUTCLR = PIN2_bm;\r\n    }\r\n}<\/pre>\r\n\n<h4 class=\"wp-block-heading\">Setting up Interrupts<\/h4>\n\n<p>The following is a simple example of an interrupt on PA1. Apart from the button, which should provide a LOW signal when pressed this time, you use the setup of the last example.  Note that the interrupt is not automatically cleared by calling the ISR. You must &#8220;manually&#8221; clear the bit in the relevant interrupt flag register.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"external_pin_interrupt.ino\" data-enlighter-title=\"external_pin_interrupt.ino\">volatile bool event = false;\r\n\r\nISR(PORTA_PORT_vect){\r\n    PORTA.INTFLAGS = PIN1_bm; \/\/ clear interrupt (writing a \"1\" clears the bit!)\r\n    event = true;\r\n}\r\n\r\nvoid setup() {\r\n    PORTA.DIRSET = PIN2_bm;\r\n    PORTA.DIRCLR = PIN1_bm;  \/\/ redundant in this case\r\n    PORTA.PIN1CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc; \/\/ Pull-Up \/ Interrupt n both edges\r\n}\r\n\r\nvoid loop(){\r\n    if(event){\r\n        PORTA.OUTSET = PIN2_bm;\r\n        delay(1000);\r\n        PORTA.OUTCLR = PIN2_bm;\r\n        event = false;\r\n    }\r\n}<\/pre>\r\n\n<p>An interrupt is triggered both when the button is pressed and when it is released. This is only really noticeable if the button is pressed for longer than one second. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Virtual Ports<\/h4>\n\n<p>If you use port manipulation \u00e0 la <code>PORTA.OUT = (1 &lt;&lt; 2);<\/code>, you should use the virtual port registers instead of the &#8220;normal&#8221; port registers. To do this, simply place a &#8220;V&#8221; before PORTx, i.e.: <code>VPORTA.OUT = (1 &lt;&lt; 2);<\/code>. The virtual ports are copies of the ports in the lower address space. Port manipulations are performed faster when using the virtual ports. The following code took 501 milliseconds to execute on an ATtiny3226 at 20 MHz: <\/p>\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">for(unsigned long i=0; i&lt;1000000;i++){\r\n    PORTA.OUT = 0;\r\n    PORTA.OUT = (1&lt;&lt;2);\r\n}<\/pre>\r\n\n<p>The same code, but with VPORTA.OUT instead of PORTA.OUT required 400 milliseconds. These are not major differences, but they are differences nonetheless.<\/p>\r\n<p>The available VPORTx registers are DIR, OUT, IN and INTFLAGS.<\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"portmux_module\">Reassigning Inputs \/ Outputs &#8211; PORTMUX Module<\/h2>\n\n<p>The registers of the PORTMUX module allow you to assign certain functions to alternative pins. It is best to check the PORTMUX Register Summary to see which functions these are. Here, as an example, is the PORTMUX Register Summary of the ATtiny3224\/6\/7:  <\/p>\r\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/portmux_reg_sum_322xpng-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"931\" height=\"189\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/portmux_reg_sum_322xpng-1.png\" alt=\"\" class=\"wp-image-22130\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/portmux_reg_sum_322xpng-1.png 931w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/portmux_reg_sum_322xpng-1-300x61.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/portmux_reg_sum_322xpng-1-768x156.png 768w\" sizes=\"auto, (max-width: 931px) 100vw, 931px\" \/><\/a><figcaption class=\"wp-element-caption\">Register Summary PORTMUX (example ATtiny3224\/6\/7)<\/figcaption><\/figure>\n\n<p>As an example, we redirect the output 1 of timer TCA0. The relevant PORTMUX register is TCAROUTEA. By setting the relevant bit, you change from the default to the alternative:<\/p>\r\n<ul>\r\n<li><code>PORTMUX.TCAROUTEA |= PORTMUX_TCA01_bm;<\/code><\/li>\r\n<\/ul>\r\n\n<h2 class=\"wp-block-heading\" id=\"evsys_module\">The Event System &#8211; EVSYS Module<\/h2>\n\n<p>The event system is really cool! It allows certain peripherals, i.e. timers, ADC, USART, etc., to send signals to other peripheral units without involving the CPU. Later in the article, we will have the RTC timer regularly trigger ADC measurements. Normally, you would probably do this via <code>delay()<\/code>, <code>millis()<\/code> or timer interrupts. However, all these options have certain disadvantages. <\/p>\r\n<p>3 or 6 channels are available for transmitting the event signals. The sender of the signal is called the generator, the receiver is the user. Many users have their own event control register in which further settings can be made. These registers are part of the peripheral modules.<\/p>\r\n\n<p>Generators and users can be synchronous or asynchronous to the system clock. If an asynchronous generator sends an event signal to a synchronous user, the signal must first be synchronized, which takes a few clock cycles. For now, it is only important that you have heard of the distinction.   <\/p>\r\n\n<h3 class=\"wp-block-heading\">EVSYS module of the tinyAVR series 2<\/h3>\n\n<h4 class=\"wp-block-heading\">CHANNELn Register &#8211; Definition of the Generator <\/h4>\n\n<p>In the CHANNELn registers (with n = 0 to 5) you define the generator:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evnt_channeln_series2-1024x84.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"84\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evnt_channeln_series2-1024x84.png\" alt=\"EVSYS.CHANNELs of the tinyAVR series 2\" class=\"wp-image-22112\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evnt_channeln_series2-1024x84.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evnt_channeln_series2-300x25.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evnt_channeln_series2-768x63.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evnt_channeln_series2.png 1235w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register EVSYS.CHANNELs<\/figcaption><\/figure>\n\n<p>Most generators can utilise all channels. But there are also exceptions. For example, the pins of port A can only use channels 0 to 3. Here is a small excerpt from the ATtiny3224\/6\/7 data sheet: <\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_gen_series2-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"970\" height=\"269\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_gen_series2-1.png\" alt=\"Event generators of the tinyAVR series 2 - some examples\" class=\"wp-image-22117\" style=\"object-fit:cover;width:797px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_gen_series2-1.png 970w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_gen_series2-1-300x83.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_gen_series2-1-768x213.png 768w\" sizes=\"auto, (max-width: 970px) 100vw, 970px\" \/><\/a><figcaption class=\"wp-element-caption\">Event generators of the tinyAVR series 2<\/figcaption><\/figure>\n\n<p>Select a suitable channel and assign the generator to its register (EVSYS.CHANNELn). Compose the generator name according to the following recipe: <\/p>\r\n<p>&#8220;EVSYS_&#8221; + &#8220;CHANNELn_&#8221; + Peripheral_ + Output_ + &#8220;gc&#8221;<\/p>\r\n<p>For example: <code>EVSYS_CHANNEL0_PORTA_PIN1_gc;<\/code><\/p>\r\n\n<h4 class=\"wp-block-heading\">Register USERn &#8211; Definition of the users<\/h4>\n\n<p>You define the event users in the USERn registers:<\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evsys_user_series2-1024x83.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"83\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evsys_user_series2-1024x83.png\" alt=\"Register EVSYS.USERn tinyAVR Series 2\" class=\"wp-image-22122\" style=\"width:840px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evsys_user_series2-1024x83.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evsys_user_series2-300x24.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evsys_user_series2-768x62.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_evsys_user_series2.png 1202w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register EVSYS.USERn <\/figcaption><\/figure>\n\n<p>Here is an excerpt from the table of available event users:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_users_series2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"936\" height=\"369\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_users_series2.png\" alt=\"\" class=\"wp-image-22124\" style=\"width:809px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_users_series2.png 936w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_users_series2-300x118.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/event_users_series2-768x303.png 768w\" sizes=\"auto, (max-width: 936px) 100vw, 936px\" \/><\/a><figcaption class=\"wp-element-caption\">Event users of the tinyAVR series 2 <\/figcaption><\/figure>\n\n<p>The complete table(s) can be found in the data sheet in the EVSYS chapter in the register descriptions. The names of the USER registers are composed as follows: <\/p>\r\n<p>&#8220;EVSYS.USER&#8221; + &#8220;Peripheral&#8221; + &#8220;Input&#8221;<\/p>\r\n<p>For example, <code>EVSYS.USEREVSYSEVOUTA<\/code>. You assign the channel to the USER register from which it is sent. <\/p>\r\n\n<h4 class=\"wp-block-heading\">A simple event example<\/h4>\n\n<p>For a better understanding, let&#8217;s take a look at a small example (tested on ATtiny3226). Attach an LED to PA2 and a pushbutton, which pulls the pin LOW when pressed, to PA1. <\/p>\r\n<p>Now we use PA1 as an event generator and EVOUTA (=PA2) as a user. Channels 0 to 3 are available for port A.  In the example, we use Channel 0.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"simple_event.ino\" data-enlighter-title=\"simple_event.ino\">void setup() {\r\n    PORTA.DIRCLR = PIN1_bm; \/\/ PA1 INPUT\r\n    PORTC.DIRSET = PIN2_bm; \/\/ PA2 (=EVOUTA) OUTPUT \r\n    PORTA.PIN1CTRL |= PORT_PULLUPEN_bm;\r\n   \r\n    EVSYS.CHANNEL0 = EVSYS_CHANNEL0_PORTA_PIN1_gc;  \/\/ PA1 is event generator for channel 0\r\n    EVSYS.USEREVSYSEVOUTA = EVSYS_USER_CHANNEL0_gc;  \/\/ EVOUTA is user of event channel 0  \r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>PA2, or EVOUTA, reflects the status of PA1. The LED lights up in the normal state and switches off when the button is pressed. This may not be impressive at first glance, but at second glance it is. We do not query the level of PA1, nor have we set up an external interrupt for it. In addition, there are no instructions for switching the LED in the running program. The processes are all controlled in the background without your running program having to do anything. More useful applications will follow later.&nbsp;<\/p>\r\n\n<h3 class=\"wp-block-heading\">EVSYS of the tinyAVR series 0 and 1<\/h3>\n\n<p>The event system of tinyAVR series 0 and 1 differs from that of series 2. There are separate registers for the synchronous and asynchronous generators and users. However, the basic principle is the same, which is why I won&#8217;t go into detail here. Take a look at the data sheet yourself, search for the EVSYS chapter and perhaps go to the register summary first. This will give you an overview, and you can navigate to the registers from there.   &nbsp;<\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7-1024x353.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"353\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7-1024x353.png\" alt=\"EVSYS Register Summary (example ATtiny1614\/1616\/1617)\" class=\"wp-image-22135\" style=\"width:840px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7-1024x353.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7-300x103.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7-768x265.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7-1320x455.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/evsys_reg_summary_1614_6_7.png 1345w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">EVSYS Register Summary (example ATtiny1614\/1616\/1617)<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">EVSYS example sketch for tinyAVR series 0 and 1<\/h4>\n\n<p>To help you get started, here is an example sketch for the tinyAVR series 1 and 0. It basically does the same thing as the example for series 2. I tested the sketch on an ATtiny1604 and ATtiny1614.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void setup() {\r\n    PORTA.DIRCLR = PIN1_bm; \/\/ PA1 INPUT\r\n    PORTA.DIRSET = PIN2_bm; \/\/ PA2 (=EVOUT0) OUTPUT \r\n    PORTA.PIN1CTRL |= PORT_PULLUPEN_bm;\r\n   \r\n    PORTMUX.CTRLA |= PORTMUX_EVOUT0_bm; \/\/ Event output needs to be enabled for tinyAVR 0\/1\r\n    EVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_PORTA_PIN1_gc; \/\/ PA1 is async. event generator for channel 0\r\n    EVSYS.ASYNCUSER8 = EVSYS_ASYNCUSER8_ASYNCCH0_gc;  \/\/ ASYNCUSER8 = EVOUT0 = channel 0 user  \r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>In addition to the differences already mentioned, it is noticeable here that the &#8220;x&#8221; in the EVOUTx is a number and not a letter. It should also be noted that the event output (EVOUTx) must be activated in the PORTMUX.CTRLA register. Finally, it should also be mentioned that the SYNCUSER and ASYCUSER registers are not named by their user, but are numbered consecutively. The numbers can be found in the data sheet in the description of the (A)SYNCUSER registers.   <\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"rtc_module\">Real-Time Counter &#8211; RTC Module<\/h2>\n\n<p>The RTC module has two features, namely the 16-bit Real-Time Counter (RTC) and the Periodic Interrupt Timer (PIT). Both use the same clock source. Otherwise, the functions can be used independently of each other. The maximum clock rate is 32768 Hz, so you are more likely to control the slower processes with this module.<\/p>\r\n\n<h3 class=\"wp-block-heading\">The registers of the RTC module<\/h3>\n\n<p>Conveniently, the register landscape of the RTC module is almost identical for all tinyAVR representatives. There are differences in the calibration and the selection of clocks.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Clock Selection Register CLKSEL<\/h4>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CLKSEL-1024x82.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"82\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CLKSEL-1024x82.webp\" alt=\"tinyAVR series: Register RTC.CLKSEL\" class=\"wp-image-19280\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CLKSEL-1024x82.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CLKSEL-300x24.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CLKSEL-768x61.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CLKSEL.webp 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register RTC.CLKSEL<\/figcaption><\/figure>\n\n<p>The clock is set in the CLKSEL register. The following options are available:<\/p>\r\n<ul>\r\n<li><strong>INT32K_gc<\/strong>: 32768 Hz provided by the internal ultra low-power oscillator OSCULP32K.<\/li>\r\n<li><strong>INT1K_gc<\/strong>: Like INT32K, but with a divider of 32, i.e. 1024 Hz.<\/li>\r\n<li><strong>TOSC32K_gc:<\/strong> 32768 Hz through XOSC32K or an external clock at TOSC1.\r\n<ul>\r\n<li><strong>only applies to tinyAVR series 1 and 2.<\/strong><\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><strong>EXTCLK_gc<\/strong>: External clock generator connected to EXTCLK.<\/li>\r\n<\/ul>\r\n\n<h4 class=\"wp-block-heading\">Crystal Frequency Calibration Register CALIB (tinyAVR Series 2 only)<\/h4>\n\n<p>A really great feature of the series 2 RTC module is that you can calibrate the underlying clock using the CALIB register.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CALIB-1024x90.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"90\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CALIB-1024x90.webp\" alt=\"tinyAVR Register: RTC.CALIB\" class=\"wp-image-19278\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CALIB-1024x90.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CALIB-300x26.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CALIB-768x68.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CALIB.webp 1190w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register RTC.CALIB<\/figcaption><\/figure>\n\n<p>ERROR[6:0] is the deviation in ppm. If SIGN is set, the clock is correspondingly faster. In this case, you must set the prescaler to at least DIV2. If SIGN is not set, the clock is slower.&nbsp;<\/p>\r\n\n<h4 class=\"wp-block-heading\">RTC Control Register A CTRLA<\/h4>\n\n<p>In the CTRLA register, you specify whether the RTC module should continue to run in standby mode (RUNSTDBY). You also (de)activate the calibration (CORREN, if available) and switch on the module (RTCEN).<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CTRLA-1024x87.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"87\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CTRLA-1024x87.webp\" alt=\"tinyAVR Register: RTC.CTRLA\" class=\"wp-image-19284\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CTRLA-1024x87.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CTRLA-300x26.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CTRLA-768x66.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CTRLA.webp 1195w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register RTC.CTRLA<\/figcaption><\/figure>\n\n<p>You can use the PRESCALER to slow down the RTC with a maximum factor of 32768:<\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_DIV_table-1024x381.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"381\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_DIV_table-1024x381.webp\" alt=\"PRESCALER[3:0] Bit Group Configurations \" class=\"wp-image-19290\" style=\"width:640px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_DIV_table-1024x381.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_DIV_table-300x112.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_DIV_table-768x286.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_DIV_table.webp 1027w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">PRESCALER[3:0] Bit Group Configurations <\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">RTC Interrupt Control Register INTCTRL<\/h4>\n\n<p>A Compare Match and an Overflow Interrupt are available for the RTC. The corresponding Interrupt Flag Register INTFLAG is similar.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_INTCTRL-1024x85.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"85\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_INTCTRL-1024x85.webp\" alt=\"tinyAVR Register: RTC.INTCTRL \/ RTC.INTFLAGS\" class=\"wp-image-19286\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_INTCTRL-1024x85.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_INTCTRL-300x25.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_INTCTRL-768x64.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_INTCTRL.webp 1220w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register RTC.INTCTRL \/ RTC.INTFLAGS<\/figcaption><\/figure>\n\n<p>There is only one interrupt vector, namely RTC_CNT_vector, i.e. you have to look in the INTFLAGS register to see which interrupt was triggered.<\/p>\r\n\n<h4 class=\"wp-block-heading\">PIT Control Register A CTRLA<\/h4>\n\n<p>The Periodic Interrupt Timer simply does what its name suggests: It triggers an interrupt at regular intervals. In the PITCTRLA register, you can activate the PIT and set the period.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITCTRLA-1024x89.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"89\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITCTRLA-1024x89.webp\" alt=\"tinyAVR Register: RTC.PITCTRLA\" class=\"wp-image-19282\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITCTRLA-1024x89.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITCTRLA-300x26.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITCTRLA-768x67.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITCTRLA.webp 1220w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register RTC.PITCTRLA<\/figcaption><\/figure>\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CYCLE_table.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1023\" height=\"381\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CYCLE_table.webp\" alt=\"PERIOD[3:0] Bit Group Configurations\" class=\"wp-image-19288\" style=\"width:675px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CYCLE_table.webp 1023w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CYCLE_table-300x112.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_CYCLE_table-768x286.webp 768w\" sizes=\"auto, (max-width: 1023px) 100vw, 1023px\" \/><\/a><figcaption class=\"wp-element-caption\">PERIOD[3:0] Bit Group Configurations<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">PIT Interrupt Control Register PITINTCTRL<\/h4>\n\n<p>In PITINTCRTL you activate the PIT interrupt. PITINTFLAGS is similar to PITINTCTRL.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITINTCTRL-1024x81.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"81\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITINTCTRL-1024x81.webp\" alt=\"RTC.PITINTCTRL \/ RTC.PITINTFLAGS\" class=\"wp-image-19292\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITINTCTRL-1024x81.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITINTCTRL-300x24.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITINTCTRL-768x61.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_RTC_PITINTCTRL.webp 1241w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register RTC.PITINTCTRL \/ RTC.PITINTFLAGS<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\">Example Sketches for RTC and PIT<\/h3>\n\n<h4 class=\"wp-block-heading\">RTC example sketch<\/h4>\n\n<p>As a simple example for programming the RTC, a sketch follows, which generates a &#8220;slow motion PWM&#8221; with a period of 2 seconds and a duty cycle of 75 % at PA2.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"rtc_example.ino\" data-enlighter-title=\"rtc_example.ino\">ISR(RTC_CNT_vect){\r\n    if(RTC.INTFLAGS &amp; RTC_CMP_bm){ \/\/ check for CMP interrupt\r\n        RTC.INTFLAGS = RTC_CMP_bm; \/\/ delete CMP interrupt flag\r\n        PORTA.OUTCLR = PIN2_bm; \/\/ PA2 = LOW\r\n    }\r\n    if(RTC.INTFLAGS &amp; RTC_OVF_bm){ \/\/ check for OVF interrupt\r\n        RTC.INTFLAGS = RTC_OVF_bm; \/\/ delete OVF interrupt flag\r\n        PORTA.OUTSET = PIN2_bm;  \/\/ PA2 = HIGH\r\n    }\r\n}\r\n\r\nvoid setup() {\r\n    delay(1);\r\n    PORTA.DIRSET = PIN2_bm;\r\n    RTC.CLKSEL = RTC_CLKSEL_INT32K_gc; \/\/ set internal clock @ 32768 Hz\r\n    RTC.PER = 16383;  \/\/ TOP = 16383\r\n    RTC.CMP = 12288;  \/\/ Compare value = 12288\r\n    RTC.INTCTRL = RTC_CMP_bm | RTC_OVF_bm;  \/\/ enable CMP and OVF interrupts\r\n    RTC.CTRLA = RTC_PRESCALER_DIV4_gc | RTC_RTCEN_bm; \/\/ Prescaler = 4 and enable RTC\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>As only one interrupt vector (RTC_CNT_vect) is available for the Overflow and Compare Interrupt, we have to use the interrupt flags to check which event triggered the interrupt.<\/p>\r\n<p>The prescaler is set to 4, i.e. the RTC counts at a frequency of 32768 \/ 4 = 8192 Hz. PER is 16383 and therefore the RTC overflows every 16384 steps, which corresponds to an overflow frequency of 2 seconds. The Compare Value is 12288, i.e. 75% of PER +1.<\/p>\r\n\n<h4 class=\"wp-block-heading\">PIT example sketch 1<\/h4>\n\n<p>The example sketch for the PIT is even simpler. With a period of 16384 and a clock rate of 32768 Hz, an interrupt is triggered every 0.5 seconds. We use it here to toggle PA2.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"pit_example.ino\" data-enlighter-title=\"pit_example.ino\">ISR(RTC_PIT_vect){\r\n    RTC.PITINTFLAGS = RTC_PI_bm; \/\/ clear PIT interrupt flag\r\n    PORTA.OUTTGL = PIN2_bm; \/\/ toggle PA2\r\n}\r\n\r\nvoid setup() {\r\n    PORTA.DIRSET = PIN2_bm;\r\n    RTC.CLKSEL = RTC_CLKSEL_INT32K_gc; \/\/ set internal clock @ 32768 Hz\r\n    RTC.PITINTCTRL = RTC_PI_bm;  \/\/ enable PIT interrupt\r\n    RTC.PITCTRLA = RTC_PERIOD_CYC16384_gc | RTC_PITEN_bm; \/\/ interrupt frq.: 2 Hz\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<h4 class=\"wp-block-heading\">PIT example sketch 2<\/h4>\n\n<p>However, you can also achieve the same without an interrupt by using PIT as an event generator. The event signal has a duty cycle of 50%. Here is a version for an ATtiny1614:  <\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"pit_example_2.ino\" data-enlighter-title=\"pit_example_2.ino\">void setup() {\r\n    PORTA.DIRSET = PIN2_bm;\r\n    RTC.CLKSEL = RTC_CLKSEL_INT1K_gc; \/\/ set internal clock @ 1.024 kHz\r\n    RTC.PITCTRLA = RTC_PITEN_bm; \r\n    PORTMUX.CTRLA |= PORTMUX_EVOUT0_bm; \/\/ Event output needs to be enabled for tinyAVR 0\/1\r\n    EVSYS.ASYNCCH3 = EVSYS_ASYNCCH3_PIT_DIV1024_gc; \/\/ Event freq. = 1024 \/ 1024 = 1 [Hz]\r\n    EVSYS.ASYNCUSER8 = EVSYS_ASYNCUSER8_ASYNCCH3_gc;\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<h2 class=\"wp-block-heading\" id=\"wdt_module\">Watchdog Timer &#8211; WDT Module<\/h2>\n\n<h3 class=\"wp-block-heading\">The registers of the WDT Module<\/h3>\n\n<p>The watchdog timer behaves in the same way on all members of the tinyAVR family. I find two features particularly remarkable: <\/p>\r\n<ul>\r\n<li>The WDT does not have an interrupt vector.&nbsp;<\/li>\r\n<li>A WDT timeout always leads to a reset.<\/li>\r\n<\/ul>\r\n<p>The Watchdog Timer (WDT) receives its clock from the ultra low-power oscillator, OSCULP32K.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Control A Register CTRLA<\/h4>\n\n<p>You enter the timing parameters for the WDT in control register A, CTRLA.<\/p>\r\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_CTRLA-1024x81.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"81\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_CTRLA-1024x81.webp\" alt=\"tinyAVR Register: WDT.CTRLA\" class=\"wp-image-19323\" style=\"width:840px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_CTRLA-1024x81.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_CTRLA-300x24.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_CTRLA-768x61.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_CTRLA.webp 1185w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register WDT.CTRLA<\/figcaption><\/figure>\n\n<p>You can make the following settings for PERIOD and WINDOW:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/wdt_ctrla_settings-1024x404.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"404\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/wdt_ctrla_settings-1024x404.webp\" alt=\"WINDOW[3:0] \/ PERIOD[3:0] Bit Group Configurations\" class=\"wp-image-19325\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/wdt_ctrla_settings-1024x404.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/wdt_ctrla_settings-300x118.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/wdt_ctrla_settings-768x303.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/wdt_ctrla_settings.webp 1213w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">WINDOW[3:0] \/ PERIOD[3:0] Bit Group Configurations<\/figcaption><\/figure>\n\n<p>If you only set a value for PERIOD and keep WINDOW at 0, the WDT will run in Normal Mode. If no watchdog reset takes place within the time period defined with PERIOD, a system reset is carried out.<\/p>\r\n<p>If WINDOW is not zero, you are in Window Mode. This is a little more difficult to explain, and perhaps only becomes clear with the example sketch. The following applies in window mode:<\/p>\r\n<ul>\r\n<li>After initialization or a <code>wdt_reset()<\/code>, the WDT is in the period defined by WINDOW. The data sheet calls this period &#8220;closed window time-out period&#8221; (TO<sub>WDTW<\/sub>). The WDT cannot be reset during this period.&nbsp; A <code>wdt_reset()<\/code> within this period leads to an immediate system reset.<\/li>\r\n<li>After the TO<sub>WDTW<\/sub>, the &#8220;normal window time-out period&#8221; (TO<sub>WDT<\/sub>) begins, the length of which you specify with PERIOD. If a <code>wdt_reset()<\/code> is received during this time, the game starts again from the beginning with the TO<code>WDTW<\/code>.<\/li>\r\n<li>If there is no <code>wdt_reset()<\/code> in the TO<sub>WDTW<\/sub> + TO<sub>WDT<\/sub> period, a system reset is carried out.<\/li>\r\n<\/ul>\r\n\n<h4 class=\"wp-block-heading\">Status Register STATUS <\/h4>\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_STATUS-1024x80.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"80\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_STATUS-1024x80.webp\" alt=\"tinyAVR Register: WDT.STATUS\" class=\"wp-image-19327\" style=\"width:845px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_STATUS-1024x80.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_STATUS-300x23.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_STATUS-768x60.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_WDT_STATUS.webp 1191w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register WDT.STATUS<\/figcaption><\/figure>\n\n<p>By setting the LOCK bit, you protect the WDT settings against changes. You can only delete it again in debug mode.<\/p>\r\n<p>If you write data to the CTRLA register, it must be transferred to the WDT clock domain. The SYNCBUSY bit is set during synchronization.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Example Sketch for the WDT<\/h3>\n\n<p>Normal mode should not require an example sketch. We will therefore only look at one sketch for window mode.  The setting for the WDT is: TO<sub>WDTW<\/sub> = TO<sub>WDT<\/sub> = 4 seconds.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"wdt.ino\" data-enlighter-title=\"wdt.ino\">#include &lt;avr\/wdt.h&gt;\r\nvoid setup(){\r\n    Serial.begin(115200);\r\n    Serial.println(\"*******************\");\r\n    Serial.println(\"Watchdog Timer Test\");\r\n    Serial.println(\"Sketch starts...\");\r\n    CPU_CCP = CCP_IOREG_gc; \/\/ allow changes\r\n    WDT.CTRLA = WDT_WINDOW_4KCLK_gc | WDT_PERIOD_4KCLK_gc; \/\/ 4s period and window\r\n    CPU_CCP = CCP_IOREG_gc;\r\n    WDT.STATUS = WDT_LOCK_bm;\r\n    while(WDT.STATUS &amp; WDT_SYNCBUSY_bm){} \/\/ wait until WDT is synchronized\r\n    wdt_reset();\r\n    int seconds = 0;\r\n    while(seconds &lt; 100){\r\n        \/\/ if(seconds == 5){  \/\/ try also 3\r\n        \/\/     wdt_reset();\r\n        \/\/ }\r\n        Serial.print(seconds);\r\n        Serial.println(\" seconds\");\r\n        delay(1000);\r\n        seconds++;\r\n    }\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>If you let the sketch run unchanged, the while() loop counts up until TO<sub>WDTW<\/sub> + TO<code>WDT<\/code> = 8 seconds have passed. The last output is &#8220;7 seconds&#8221; because once the eighth second has been reached, there is no more time for the output of &#8220;8 seconds&#8221;.<\/p>\r\n<p>If you uncomment lines 15 to 17, there is a <code>wdt_reset()<\/code> at fifth second, i.e. in the &#8220;allowed&#8221; TO<sub>WDT<\/sub> period. The WDT then runs for a further eight seconds until the system reset is carried out.<\/p>\r\n<p>If you then change line 15 so that the <code>wdt_reset()<\/code> occurs after three seconds, there will be an immediate system reset as you are in the &#8220;forbidden&#8221; TO<sub>WDTW<\/sub> period.<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/output_wdt_sketch.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"871\" height=\"353\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/output_wdt_sketch.webp\" alt=\"Output wdt.ino - left: unchanged, center: &quot;if (seconds == 5)&quot;, right: &quot;if(seconds ==3)&quot; \" class=\"wp-image-19337\" style=\"width:840px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/output_wdt_sketch.webp 871w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/output_wdt_sketch-300x122.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/output_wdt_sketch-768x311.webp 768w\" sizes=\"auto, (max-width: 871px) 100vw, 871px\" \/><\/a><figcaption class=\"wp-element-caption\">Output wdt.ino &#8211; left: unchanged, center: &#8220;if (seconds == 5)&#8221;, right: &#8220;if(seconds ==3)&#8221; <\/figcaption><\/figure>\n\n<p>And what&#8217;s the point of all this? The watchdog normally bites if the sketch gets stuck somewhere. You can use the window method to trigger a system reset if an action is executed too early, for example because some other step has not been executed for whatever reason.<\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"adc_module\">A\/D Converter &#8211; ADCn Module<\/h2>\n\n<p>The A\/D converter of the tinyAVR microcontroller would certainly deserve a separate article. However, I will keep this chapter short and once again refer to the data sheets. <\/p>\r\n<p>The ADC modules of tinyAVR series 0 and 1 differ fundamentally from those of series 2.<\/p>\r\n\n<h3 class=\"wp-block-heading\">ADCn of the tinyAVR series 0\/1<\/h3>\n\n<p>Here is the identical register structure for all tinyAVR MCUs of series 0 and 1:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_Summary_ADC-1.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1018\" height=\"574\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_Summary_ADC-1.webp\" alt=\"Register Summary ADCn\" class=\"wp-image-19381\" style=\"width:778px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_Summary_ADC-1.webp 1018w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_Summary_ADC-1-300x169.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_Summary_ADC-1-768x433.webp 768w\" sizes=\"auto, (max-width: 1018px) 100vw, 1018px\" \/><\/a><figcaption class=\"wp-element-caption\">Register Summary ADCn of tinyAVR series 0 and 1<\/figcaption><\/figure>\n\n<p>I would like to explain a few selected register settings:<\/p>\r\n<ul>\r\n<li><strong>RUNSTBY<\/strong>: Allows the ADC to be operated in standby mode.<\/li>\r\n<li><strong>RESSEL<\/strong>: If you set this bit, the resolution is reduced from 10 to 8 bits.<\/li>\r\n<li><strong>FREERUN<\/strong>: Continuous mode.<\/li>\r\n<li><strong>SAMPNUM<\/strong>: You can add up to 64 results per measurement. 2^6 results times 2^10 resolution gives a result with a size of 2^16 bits, which still fits into the RES result register.<\/li>\r\n<li><strong>PRESC<\/strong>: Divider for the clock rate of the ADC.<\/li>\r\n<li><strong>REFSEL<\/strong>: Selection of the reference voltage. The following options are available: INTREF (Internal Reference), VDDREF and VREFA (External Reference, not for ). Confusingly, the data sheet states &#8220;INTERNAL&#8221; and &#8220;VDD&#8221; instead of INTREF or VDDREF. <\/li>\r\n<li><strong>SAMPLEN<\/strong>: Extends the measuring time up to a maximum factor of 31.<\/li>\r\n<li><strong>MUXPOS<\/strong>: Defines the input for the ADC. The table with the bit group configurations can be found in the data sheet.<\/li>\r\n<li><strong>STARTCONV<\/strong>: Starts a measurement.<\/li>\r\n<\/ul>\r\n\n<p>The internal reference is specified in the VREF.CTRLA register. To do this, set the bit group ADC0REFSEL[2:0]. The Bit Group Configurations are called <em>VREF_ADC0REFSEL_xxx_gc<\/em> with<\/p>\r\n<ul>\r\n<li><em>xxx <\/em>= 0V55, 1V1, 2V5V, 4V34 V or 1V5 for 0.55, 1.1, 2.5, 4.34 or 1.5 volts.<\/li>\r\n<\/ul>\r\n\n<h3 class=\"wp-block-heading\">Example sketches for the ADC (tinyAVR series 0\/1)<\/h3>\n\n<h4 class=\"wp-block-heading\">Simple A\/D measurement (series 0\/1)<\/h4>\n\n<p>In the following example sketch, we measure the voltage at A2. We use the internal 4.34 V reference voltage.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"adc_example_series_0_1.ino\" data-enlighter-title=\"adc_example_series_0_1.ino\">void setup() {\r\n    Serial.begin(115200);\r\n    PORTA.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; \/\/ Disable digital buffer\r\n    ADC0.CTRLA = ADC_ENABLE_bm; \/\/ Enable ADC\r\n    ADC0.CTRLC = ADC_REFSEL_INTREF_gc | ADC_PRESC_DIV16_gc; \/\/ use internal reference \/ prescaler: 16\r\n    VREF.CTRLA = VREF_ADC0REFSEL_4V34_gc; \/\/ use internal 4.34 V reference \r\n    ADC0.MUXPOS = ADC_MUXPOS_AIN3_gc; \/\/ use A3 as input\r\n    ADC0.SAMPCTRL = 0;\r\n}\r\n\r\nvoid loop(){\r\n    ADC0.COMMAND = ADC_STCONV_bm; \/\/ Start Conversion\r\n    while((ADC0.INTFLAGS &amp; ADC_RESRDY_bm) == 0){} \/\/ Waiting for the result\r\n    float result = ADC0.RES * 4340.0 \/ 1024.0;\r\n    Serial.print(\"Voltage [mV]: \");\r\n    Serial.println(result);\r\n    delay(1000);\r\n}<\/pre>\r\n\n<h4 class=\"wp-block-heading\">ADC0 &#8211; RTC controlled (Series 0\/1)<\/h4>\n\n<p>Let me come back to the events. The following sketch uses the RTC to initiate an ADC conversion every two seconds.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"rtc_controlled_adc_series_0_1.ino\" data-enlighter-title=\"rtc_controlled_adc_series_0_1.ino\">volatile bool adcReady = false;\r\n\r\nISR(ADC0_RESRDY_vect){\r\n    adcReady=true;\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    PORTA.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;\r\n    ADC0.CTRLA = ADC_ENABLE_bm;\r\n    ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL_INTREF_gc | ADC_PRESC_DIV16_gc;\r\n    VREF.CTRLA = VREF_ADC0REFSEL_4V34_gc;\r\n    ADC0.MUXPOS = ADC_MUXPOS_AIN3_gc; \/\/ A3\r\n    ADC0.SAMPCTRL = 0;\r\n    ADC0.EVCTRL = ADC_STARTEI_bm; \/\/ initiate measurement by event\r\n    ADC0.INTCTRL = ADC_RESRDY_bm; \/\/ enable result ready interrupt\r\n    RTC.CLKSEL |= RTC_CLKSEL_INT32K_gc; \/\/ use internal 32 kHz clock\r\n    RTC.PER = 63; \/\/ overflow after 63 (64 steps) \r\n    RTC.CTRLA = RTC_PRESCALER_DIV1024_gc | RTC_RTCEN_bm; \/\/ OVF frequency = 0.5 Hz\r\n    \r\n    EVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_RTC_OVF_gc; \/\/ RTC overflow is event generator\r\n    EVSYS.ASYNCUSER1 = EVSYS_ASYNCUSER1_ASYNCCH0_gc; \/\/ ADC0 is event user\r\n}\r\n\r\nvoid loop(){\r\n    if(adcReady){ \r\n        float result = ADC0.RES * 4340.0 \/ 1024.0;\r\n        Serial.print(\"Voltage [mV]: \");\r\n        Serial.println(result);\r\n        adcReady = false;\r\n    }\r\n}<\/pre>\r\n\n<p>Without the event system, you would have to set up a timer interrupt or apply a construction with <code>delay()<\/code> or <code>millis()<\/code> to start measurements at 2-second intervals. You would then have to wait or be informed via another interrupt when the conversion result is available. In the example above, however, a single interrupt is sufficient, everything else is done in the background.<\/p>\r\n\n<h3 class=\"wp-block-heading\">ADCn of the tinyAVR series 2<\/h3>\n\n<p>Here is the register overview for the ADCn module of the tinyAVR series 2:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_sum_adc_series_2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"931\" height=\"719\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_sum_adc_series_2.png\" alt=\"\" class=\"wp-image-22155\" style=\"width:716px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_sum_adc_series_2.png 931w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_sum_adc_series_2-300x232.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_sum_adc_series_2-768x593.png 768w\" sizes=\"auto, (max-width: 931px) 100vw, 931px\" \/><\/a><figcaption class=\"wp-element-caption\">Register Summary ADCn of the tinyAVR Series 2<\/figcaption><\/figure>\n\n<p>Important technical differences are:<\/p>\r\n<ul>\r\n<li>The ADC has a maximum resolution of 12 bits.<\/li>\r\n<li>The input signal can be amplified up to 16 times.<\/li>\r\n<li>The options for the reference voltages are: 1V024, 2V048, 2V500 or 4V096 for 1,024, 2,048, 2,500 or 4,096 volts respectively.<\/li>\r\n<\/ul>\r\n\n<h3 class=\"wp-block-heading\">Example sketches for the ADC (tinyAVR Series 2)<\/h3>\n\n<h4 class=\"wp-block-heading\">Simple A\/D measurement (Series 2)<\/h4>\n\n<p>This is what the sketch for a simple ADC conversion would look like:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"adc_example_series_2.ino\" data-enlighter-title=\"adc_example_series_2.ino\">void setup() {\r\n    Serial.begin(115200);\r\n    PORTA.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc; \/\/ Disable digital buffer\r\n    ADC0.CTRLA = ADC_ENABLE_bm; \/\/ Enable ADC\r\n    ADC0.CTRLC = ADC_REFSEL_4096MV_gc; \r\n    ADC0.CTRLB = ADC_PRESC_DIV16_gc; \/\/ use internal reference \/ prescaler: 16\r\n    ADC0.MUXPOS = ADC_MUXPOS_AIN3_gc; \/\/ use A3 as input\r\n}\r\n\r\nvoid loop(){\r\n    ADC0.COMMAND = ADC_MODE_SINGLE_12BIT_gc | ADC_START_IMMEDIATE_gc; \/\/ Start Conversion\r\n    while((ADC0.INTFLAGS &amp; ADC_RESRDY_bm) == 0){} \/\/ Waiting for the result\r\n    float result = ADC0.RESULT; \/\/ * 4096.0 \/ 4096.0 = 1\r\n    Serial.print(\"Voltage [mV]: \");\r\n    Serial.println(result);\r\n    delay(1000);\r\n}<\/pre>\r\n\n<h4 class=\"wp-block-heading\">ADC0 &#8211; RTC controlled (Series 2)<\/h4>\n\n<p>And here is the &#8220;translation&#8221; of the RTC-controlled ADC conversion for series 2:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"rtc_controlled_adc_series_2.ino\" data-enlighter-title=\"rtc_controlled_adc_series_2.ino\">volatile bool adcReady = false;\r\n\r\nISR(ADC0_RESRDY_vect){\r\n    adcReady=true;\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    PORTA.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;\r\n    ADC0.CTRLC = ADC_REFSEL_4096MV_gc; \r\n    ADC0.CTRLB = ADC_PRESC_DIV16_gc; \/\/ use internal reference \/ prescaler: 16\r\n    ADC0.MUXPOS = ADC_MUXPOS_AIN3_gc; \/\/ use A3 as input\r\n    ADC0.COMMAND = ADC_MODE_SINGLE_12BIT_gc | ADC_START_EVENT_TRIGGER_gc;\r\n    ADC0.INTCTRL = ADC_RESRDY_bm; \/\/ enable result ready interrupt\r\n    RTC.CLKSEL |= RTC_CLKSEL_INT32K_gc; \/\/ use internal 32 kHz clock\r\n    RTC.PER = 63; \/\/ overflow after 63 (64 steps) \r\n    RTC.CTRLA = RTC_PRESCALER_DIV1024_gc | RTC_RTCEN_bm; \/\/ OVF frequency = 0.5 Hz\r\n    \r\n    EVSYS.CHANNEL0 = EVSYS_CHANNEL0_RTC_OVF_gc; \/\/ RTC overflow is event generator\r\n    EVSYS.USERADC0START = EVSYS_USER_CHANNEL0_gc; \/\/ ADC0 is event user\r\n}\r\n\r\nvoid loop(){\r\n    if(adcReady){ \r\n        float result = ADC0.RESULT * 4096.0 \/ 4096.0;\r\n        Serial.print(\"Voltage [mV]: \");\r\n        Serial.println(result);\r\n        adcReady = false;\r\n    }\r\n}<\/pre>\r\n","protected":false},"excerpt":{"rendered":"<p>The microcontrollers of the tinyAVR family differ significantly from the classic ATtinys. This is an introduction to programming at register level.  <\/p>\n","protected":false},"author":1,"featured_media":15558,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[543],"tags":[1498,556,2575,2255,691,1886,2576,2263,2253,1958,1565,1885,1050,2262],"class_list":["post-22202","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-boards-and-microcontrollers","tag-adc-en","tag-arduino-en-2","tag-event-en","tag-evsys-en","tag-interrupt-en-2","tag-megatinycore-en","tag-periodic-interrupt-en","tag-pit-en","tag-portmux-en","tag-register-en","tag-rtc-en","tag-tinyavr-en","tag-watchdog-en","tag-wdt-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Programming the tinyAVR series 0, 1, 2 - Part 1 &#8226; Wolles Elektronikkiste<\/title>\n<meta name=\"description\" content=\"The MCUs of the tinyAVR family differ significantly from the classic ATtinys. An introduction to programming at register level.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Programming the tinyAVR series 0, 1, 2 - Part 1 &#8226; Wolles Elektronikkiste\" \/>\n<meta property=\"og:description\" content=\"The MCUs of the tinyAVR family differ significantly from the classic ATtinys. An introduction to programming at register level.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1\" \/>\n<meta property=\"og:site_name\" content=\"Wolles Elektronikkiste\" \/>\n<meta property=\"article:published_time\" content=\"2024-10-09T21:10:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-12-01T17:15:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"1200\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Wolfgang Ewald\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfgang Ewald\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"25 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1\"},\"author\":{\"name\":\"Wolfgang Ewald\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"headline\":\"Programming the tinyAVR series 0, 1, 2 &#8211; Part 1\",\"datePublished\":\"2024-10-09T21:10:06+00:00\",\"dateModified\":\"2024-12-01T17:15:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1\"},\"wordCount\":3875,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"keywords\":[\"ADC\",\"Arduino\",\"event\",\"EVSYS\",\"Interrupt\",\"megaTinyCore\",\"periodic interrupt\",\"PIT\",\"PORTMUX\",\"Register\",\"RTC\",\"tinyAVR\",\"watchdog\",\"WDT\"],\"articleSection\":[\"Boards and Microcontrollers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1\",\"name\":\"Programming the tinyAVR series 0, 1, 2 - Part 1 &#8226; Wolles Elektronikkiste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"datePublished\":\"2024-10-09T21:10:06+00:00\",\"dateModified\":\"2024-12-01T17:15:04+00:00\",\"description\":\"The MCUs of the tinyAVR family differ significantly from the classic ATtinys. An introduction to programming at register level.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"width\":1200,\"height\":1200},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/programming-the-tinyavr-series-0-1-2-part-1#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programming the tinyAVR series 0, 1, 2 &#8211; Part 1\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\",\"name\":\"Wolles Elektronikkiste\",\"description\":\"Die wunderbare Welt der Elektronik\",\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\",\"name\":\"Wolfgang Ewald\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"width\":512,\"height\":512,\"caption\":\"Wolfgang Ewald\"},\"logo\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Programming the tinyAVR series 0, 1, 2 - Part 1 &#8226; Wolles Elektronikkiste","description":"The MCUs of the tinyAVR family differ significantly from the classic ATtinys. An introduction to programming at register level.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1","og_locale":"en_US","og_type":"article","og_title":"Programming the tinyAVR series 0, 1, 2 - Part 1 &#8226; Wolles Elektronikkiste","og_description":"The MCUs of the tinyAVR family differ significantly from the classic ATtinys. An introduction to programming at register level.","og_url":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1","og_site_name":"Wolles Elektronikkiste","article_published_time":"2024-10-09T21:10:06+00:00","article_modified_time":"2024-12-01T17:15:04+00:00","og_image":[{"width":1200,"height":1200,"url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","type":"image\/jpeg"}],"author":"Wolfgang Ewald","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Wolfgang Ewald","Est. reading time":"25 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#article","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1"},"author":{"name":"Wolfgang Ewald","@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"headline":"Programming the tinyAVR series 0, 1, 2 &#8211; Part 1","datePublished":"2024-10-09T21:10:06+00:00","dateModified":"2024-12-01T17:15:04+00:00","mainEntityOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1"},"wordCount":3875,"commentCount":0,"publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","keywords":["ADC","Arduino","event","EVSYS","Interrupt","megaTinyCore","periodic interrupt","PIT","PORTMUX","Register","RTC","tinyAVR","watchdog","WDT"],"articleSection":["Boards and Microcontrollers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1","url":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1","name":"Programming the tinyAVR series 0, 1, 2 - Part 1 &#8226; Wolles Elektronikkiste","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#website"},"primaryImageOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","datePublished":"2024-10-09T21:10:06+00:00","dateModified":"2024-12-01T17:15:04+00:00","description":"The MCUs of the tinyAVR family differ significantly from the classic ATtinys. An introduction to programming at register level.","breadcrumb":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#primaryimage","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","width":1200,"height":1200},{"@type":"BreadcrumbList","@id":"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/wolles-elektronikkiste.de\/en"},{"@type":"ListItem","position":2,"name":"Programming the tinyAVR series 0, 1, 2 &#8211; Part 1"}]},{"@type":"WebSite","@id":"https:\/\/wolles-elektronikkiste.de\/en#website","url":"https:\/\/wolles-elektronikkiste.de\/en","name":"Wolles Elektronikkiste","description":"Die wunderbare Welt der Elektronik","publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wolles-elektronikkiste.de\/en?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46","name":"Wolfgang Ewald","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","width":512,"height":512,"caption":"Wolfgang Ewald"},"logo":{"@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png"}}]}},"_links":{"self":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/22202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/comments?post=22202"}],"version-history":[{"count":4,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/22202\/revisions"}],"predecessor-version":[{"id":22948,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/22202\/revisions\/22948"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media\/15558"}],"wp:attachment":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media?parent=22202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/categories?post=22202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/tags?post=22202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}