DAC - Sam D21 Bare Code Driver - Page 1
Forum section: electronics / general

author: Franc
author_rank: Regular Contributor
timestamp: October 09, 2016, 09:31:32 pm
content: Hi friends!I am starting to use the DAC of Sam D21 .I would like to code it in Bare Metal.Anyone has an example driver configuration to me study together DS? I have some doubts to coding it.Best Regards

author: ataradov
author_rank: Super Contributor
timestamp: October 09, 2016, 10:33:28 pm
content: What you've got so far and what does not work?

author: rstofer
author_rank: Super Contributor
timestamp: October 09, 2016, 11:57:45 pm
content: Why not start with the App Note?http://www.atmel.com/Images/Atmel-42110-SAM0-Digital-to-Analog-(DAC)-Driver_Application%20Note_AT03244.pdf

author: ataradov
author_rank: Super Contributor
timestamp: October 09, 2016, 11:59:10 pm
content: Quote from: rstofer on October 09, 2016, 11:57:45 pmThe question is about bare-metal implementation and this AN can't be any further away from that.

author: Franc
author_rank: Regular Contributor
timestamp: October 10, 2016, 12:31:17 am
content: Hi RSTOFER, yes I checked that file but all information is in ASF. I do not like ASF.I searched a lot the driver configuration in Bare Code like that ASF file shows but no success for Bare Code.Dear Alex, I cannot understand how I can do the syncronization for write data to DATA.reg.Regards

author: ataradov
author_rank: Super Contributor
timestamp: October 10, 2016, 12:38:42 am
content: Quote from: Franc on October 10, 2016, 12:31:17 amDon't think about synchronization. It is not going to affect you in this case.

author: Franc
author_rank: Regular Contributor
timestamp: October 10, 2016, 12:48:39 am
content: Alex, in page 934 of DS means:'The following bits need synchronization when written:• Software Reset bit in the Control A register (CTRLA.SWRST)• Enable bit in the Control A register (CTRLA.ENABLE)• All bits in the Data register (DATA)• All bits in the Data Buffer register (DATABUF)so, the STATUS.SYNCBUSY is not relevant?Thanks friend!!!

author: ataradov
author_rank: Super Contributor
timestamp: October 10, 2016, 12:53:22 am
content: Quote from: Franc on October 10, 2016, 12:48:39 amSynchronization is needed if you are worried about interrupt latency (within a few clock cycles). If you do two writes in a row into the registers that need synchronization, then the second write will block the system bus until the first one completes. If you only write DATA register once in a while, then you have noting to worry about.At the same time, it is not that hard to do the synchronization. Just do something likeCode:while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY);before the write to the DATA register.

author: Franc
author_rank: Regular Contributor
timestamp: October 10, 2016, 11:44:38 pm
content: When I debug my code with the dac_carga_init() in main.C, my program blocks.I have configured my DAC drive as below. I dont know what happens dear Alex.Code:#include "samd21.h"#include "board_defs.h"void dac_carga_init(void){PM->APBCMASK.reg |= PM_APBCMASK_DAC;// Enable peripheral clock for DACGCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID (DAC_GCLK_ID) |// DAC share same GCLKGCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN (DAC_GCLK_SOURCE);while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN);// Wait till enabledGPIO_dirOut(DAC_OUT); //PA02GPIO_pmuxen(DAC_OUT, DAC_OUT_PMUX); //PMUX B for PA02 pin DACDAC->CTRLA.reg &= ~(DAC_CTRLA_ENABLE); //Disable DAC to permit change CTRLA B register.DAC->CTRLB.reg |= DAC_CTRLB_EOEN | DAC_CTRLB_REFSEL_AVCC; //Enable the DAC output on Vout pin. Enable VDDANAL REF.DAC->CTRLA.reg |= DAC_CTRLA_ENABLE; //Enable DAC}.h file:Code:#ifndef DAC_CARGA_H_#define DAC_CARGA_H_void dac_carga_init(void);inline uint16_t dac_carga_write(uint16_t carga);uint16_t dac_carga_write(uint16_t carga){// uint16_t received_data;while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY);// Make sure clock synchronizationDAC->DATA.reg = (carga);// Write DAC value}#endifBest Regards friends!

author: ataradov
author_rank: Super Contributor
timestamp: October 11, 2016, 12:01:23 am
content: Here is a full source code that works. If you want to test this as is, you can replace main.c herehttps://github.com/ataradov/mcu-starter-projects/tree/master/samd21with this code.You can go fancy with synchronization and stuff, but as I said, it is not necessary in most cases.Code://-----------------------------------------------------------------------------#include <stdlib.h>#include <stdint.h>#include <stdbool.h>#include <string.h>#include "samd21.h"#include "hal_gpio.h"//-----------------------------------------------------------------------------HAL_GPIO_PIN(DAC, A, 2)//-----------------------------------------------------------------------------static void sys_init(void){// Switch to 8MHz clock (disable prescaler)SYSCTRL->OSC8M.bit.PRESC = 0;}//-----------------------------------------------------------------------------static void dac_init(void){HAL_GPIO_DAC_out();HAL_GPIO_DAC_pmuxen(PORT_PMUX_PMUXE_B_Val);PM->APBCMASK.reg |= PM_APBCMASK_DAC;GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(DAC_GCLK_ID) |GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);DAC->CTRLA.reg = DAC_CTRLA_SWRST;while (DAC->CTRLA.reg & DAC_CTRLA_SWRST);DAC->CTRLB.reg = DAC_CTRLB_EOEN | DAC_CTRLB_REFSEL_AVCC;DAC->CTRLA.reg = DAC_CTRLA_ENABLE;}//-----------------------------------------------------------------------------static void dac_write(uint16_t value){DAC->DATA.reg = value;}//-----------------------------------------------------------------------------int main(void){int dac_out = 0;sys_init();dac_init();while (1){dac_write(dac_out++);}return 0;}

author: Franc
author_rank: Regular Contributor
timestamp: October 11, 2016, 12:21:03 am
content: In page 33 of DS SAMD21 says that PA02 is the only pin for Vout of DAC. Is possible I use any other Analog pin for do it once all are MUX B?(PA02 til PA07 and PB00 till PB09)Thanks!

author: ataradov
author_rank: Super Contributor
timestamp: October 11, 2016, 12:22:11 am
content: Quote from: Franc on October 11, 2016, 12:21:03 amI don't understand the question.

author: Franc
author_rank: Regular Contributor
timestamp: October 11, 2016, 12:28:25 am
content: Sorry,... Could I use any other Analog Pin to DAC Vout? In DS, page 33, shows only PA02 as Vout, but I am using the PA02 with my OLED Xplained Pro in EXT03.

author: ataradov
author_rank: Super Contributor
timestamp: October 11, 2016, 12:30:23 am
content: No, the table "Table 6-1. PORT Function Multiplexing" lists all possible multiplexing options. If it is not in the table, it is impossible. In case of DAC, only PA2 is possible.

author: Franc
author_rank: Regular Contributor
timestamp: October 11, 2016, 10:37:25 pm
content: Still blocking my program when I call the dac_carga_init().I am using the SERCOM5 SPI in same EXT03.Also in my program I am using the TCC0 TC4 TC5, SERCOM0 SPI in EXT1.My GCLK(0) is DFLL 48Mhz. Do you know if there is any incompatibility to use them together DAC?Below mydac_carga_init():Code:void dac_carga_init(void){GPIO_dirOut(DAC_OUT); //PA02GPIO_pmuxen(DAC_OUT, DAC_OUT_PMUX); //PMUX B for PA02 pin DACPM->APBCMASK.reg |= PM_APBCMASK_DAC;// Enable peripheral clock for DACGCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID (DAC_GCLK_ID) |// DAC share same GCLKGCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN (0);while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN);// Wait till enabledDAC->CTRLA.reg = DAC_CTRLA_SWRST;while (DAC->CTRLA.reg & DAC_CTRLA_SWRST);DAC->CTRLB.reg = DAC_CTRLB_EOEN | DAC_CTRLB_REFSEL_AVCC; //Enable the DAC output on Vout pin. Enable VDDANAL REF.DAC->CTRLA.reg = DAC_CTRLA_ENABLE; //Enable DACwhile (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY);//Wait until clock ok.}Best Regards

author: ataradov
author_rank: Super Contributor
timestamp: October 11, 2016, 10:42:46 pm
content: Quote from: Franc on October 11, 2016, 10:37:25 pmI'm pretty sure this is wrong. And the whole line is unnecessary.

author: Franc
author_rank: Regular Contributor
timestamp: October 11, 2016, 11:02:31 pm
content: ..You are the guy..Alex! Worked perfect. Thanks.By the way.... why this line is wrong? ' while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN); // Wait till enabled'I have used it to all my TC and no issues.Regards!

author: ataradov
author_rank: Super Contributor
timestamp: October 11, 2016, 11:04:51 pm
content: If you really want to wait until the clock is enabled, then it should be "while (0==(GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN));". Your TC is probably clocked from a slower clock, so it takes a few cycles for it to enable, so it was falling though on the first iteration.In general, it probably is a good practice to wait, but in reality, even if clock is not enabled, your first access to the peripheral register will block until clock is enabled.

author: Franc
author_rank: Regular Contributor
timestamp: October 11, 2016, 11:15:24 pm
content: OK, nice clue!*Now I will start in Analog Comparators of Sam D21.Best Regards!