ADuCM3029
Recommended for New Designs
The ADuCM3027/ADuCM3029 microcontroller units (MCUs) are ultra low power microcontroller systems with integrated power management for processing, control...
Datasheet
ADuCM3029 on Analog.com
Dear all,
I need to uniquely identify a PCB that uses ADUCM3029 as micro-controller. For that i'm connecting a ROM using 1-wire protocol in a GPIO pin. I browsed the ADI drivers and examples however I didn't find anything related to this matter, so I started writing a 1-wire protocol driver to read this ROM. One of the configuration needed is a pull-up resistor connecting to this pin. I'm asking:
what is value of the internal GPIO pull-up resistors?
Did Analog Devices has already an example or documentation concerning the 1-wire protocol?
Regards,
Mohamed Amine MESSAOUD
Hello Messaoud,
The datasheet specifies that at the maximum battery supply voltage of 3.6V and 0V input on the GPIO the pull-up will sink 100uA.
http://www.analog.com/media/en/technical-documentation/data-sheets/ADuCM3027_3029.pdf
Currently there is no 1-wire example from ADI that I could find.
Regards,
Andrei.
I tried to write a driver for this DS2401 could you review it with me.
This is the one_wire_driver.h header file
#ifndef ONE_WIRE_DRIVER #define ONE_WIRE_DRIVER /* see https://www.maximintegrated.com/en/app-notes/index.mvp/id/126 */ #include <adi_processor.h> #include "ADuCM3029.H" #include <stddef.h> /* for 'NULL' */ #include <string.h> /* for strlen */ #include <stdint.h> #include <drivers/pwr/adi_pwr.h> #include <drivers/gpio/adi_gpio.h> #include <drivers/dma/adi_dma.h> #include "common.h" #include <drivers/general/adi_drivers_general.h> #define STANDARD_SPEED_A 6u #define STANDARD_SPEED_B 64u #define STANDARD_SPEED_C 60u #define STANDARD_SPEED_D 10u #define STANDARD_SPEED_E 9u #define STANDARD_SPEED_F 55u #define STANDARD_SPEED_G 0u #define STANDARD_SPEED_H 480u #define STANDARD_SPEED_I 70u #define STANDARD_SPEED_J 410u #define DS2401_READ_ROM_COMMAND 0x33 /* tick every 1us*/ #define TICKS (26000000u / 1000000u) volatile uint32_t usTicks = 0; typedef struct{ ADI_GPIO_PORT port; ADI_GPIO_DATA pins; } PinMap; void delay_us(uint32_t nus); /* 1-wire basic functions */ uint16_t OWTouchReset(PinMap _1wd_pin); void OWWriteBit(uint8_t bit,PinMap _1wd_pin); uint16_t OWReadBit(PinMap _1wd_pin); /* 1-wire drived functions */ void OWWriteByte(uint8_t data,PinMap _1wd_pin); uint8_t OWReadByte(PinMap _1wd_pin); uint8_t OWTouchByte(uint8_t data,PinMap _1wd_pin); void OWBlock(uint8_t *data, uint8_t data_len,PinMap _1wd_pin); #endif /* ONE_WIRE_DRIVER */
And this is the implementation
#include "one_wire_driver.h" /* delay in µs unit*/ void delay_us(uint32_t nus) { while (nus--) { while (usTicks != 0) { } } } /* Tick every 1µs*/ void SysTick_Handler(){ usTicks++; if(usTicks==26000000u) { usTicks=0; } } uint8_t ROM_VALUE[8]; volatile uint8_t family_code; volatile uint64_t serial_number; volatile uint8_t crc_byte; int main(void) { PinMap data_DS2401 = { ADI_GPIO_PORT1, ADI_GPIO_PIN_13 }; /* initialisations */ uint8_t gpioMemory[ADI_GPIO_MEMORY_SIZE] = {0}; ADI_PWR_RESULT ePwrResult; ADI_GPIO_RESULT eGpioResult; common_Init(); ePwrResult = adi_pwr_Init(); DEBUG_RESULT("adi_pwr_Init failed.", ePwrResult, ADI_PWR_SUCCESS); ePwrResult = adi_pwr_SetClockDivider(ADI_CLOCK_HCLK, 1u); DEBUG_RESULT("adi_pwr_SetClockDivider (HCLK) failed.", ePwrResult, ADI_PWR_SUCCESS); ePwrResult = adi_pwr_SetClockDivider(ADI_CLOCK_PCLK, 1u); DEBUG_RESULT("adi_pwr_SetClockDivider (PCLK) failed.", ePwrResult, ADI_PWR_SUCCESS); /* initialize the systick driver */ SysTick_Config(TICKS); /* Initialize GPIO driver */ eGpioResult= adi_gpio_Init(gpioMemory, ADI_GPIO_MEMORY_SIZE); DEBUG_RESULT("adi_GPIO_Init failed.", eGpioResult, ADI_GPIO_SUCCESS); /* set output enable */ eGpioResult = adi_gpio_OutputEnable(data_DS2401.port, data_DS2401.pins, true); DEBUG_RESULT("adi_GPIO_SetOutputEnable failed on data_DS2401.", eGpioResult, ADI_GPIO_SUCCESS); /* set pull up. In this case pull-up resistor is external */ //eGpioResult = adi_gpio_PullUpEnable(data_DS2401.port,data_DS2401.pins,true); //DEBUG_RESULT("adi_gpio_PullUpEnable failed on data_DS2401.", eGpioResult, ADI_GPIO_SUCCESS); eGpioResult = adi_gpio_SetHigh(data_DS2401.port, data_DS2401.pins); DEBUG_RESULT("adi_gpio_SetHigh data_DS2401.port.", eGpioResult, ADI_GPIO_SUCCESS); /* read DS2401 ROM */ if(OWTouchReset(data_DS2401)) { /* send read ROM Command */ OWWriteByte(DS2401_READ_ROM_COMMAND,data_DS2401); /* read ROM_VALUE */ OWBlock(ROM_VALUE,8,data_DS2401); /* parse family_code */ family_code=ROM_VALUE[0]; /* parse Serial_Number*/ uint8_t loop; for(loop=1;loop<8;loop++) serial_number|=(64-8*loop)>>ROM_VALUE[loop]; /* parse crc_byte */ crc_byte=ROM_VALUE[8]; } } uint16_t OWTouchReset(PinMap _1wd_pin) { uint16_t result; ADI_GPIO_RESULT eGpioResult; delay_us(STANDARD_SPEED_G); eGpioResult = adi_gpio_SetLow (_1wd_pin.port, _1wd_pin.pins); delay_us(STANDARD_SPEED_H); /* release the bus */ eGpioResult = adi_gpio_SetHigh(_1wd_pin.port, _1wd_pin.pins); delay_us(STANDARD_SPEED_I); /* Sample for presence pulse from slave */ eGpioResult = adi_gpio_GetData(_1wd_pin.port,_1wd_pin.pins,&result); delay_us(STANDARD_SPEED_J); return result; } void OWWriteBit(uint8_t bit,PinMap _1wd_pin) { ADI_GPIO_RESULT eGpioResult; eGpioResult = adi_gpio_SetLow(_1wd_pin.port, _1wd_pin.pins); if(bit) { /* write 1 bit */ delay_us(STANDARD_SPEED_A); /* release the bus */ eGpioResult = adi_gpio_SetHigh(_1wd_pin.port, _1wd_pin.pins); delay_us(STANDARD_SPEED_B); } else { /* write 0 bit */ delay_us(STANDARD_SPEED_C); /* release the bus */ eGpioResult = adi_gpio_SetHigh(_1wd_pin.port, _1wd_pin.pins); delay_us(STANDARD_SPEED_D); } } uint16_t OWReadBit(PinMap _1wd_pin) { uint16_t result; ADI_GPIO_RESULT eGpioResult; eGpioResult = adi_gpio_SetLow(_1wd_pin.port, _1wd_pin.pins); delay_us(STANDARD_SPEED_A); /* release the bus */ eGpioResult = adi_gpio_SetHigh(_1wd_pin.port, _1wd_pin.pins); delay_us(STANDARD_SPEED_E); /* Sample the bit value from slave */ eGpioResult = adi_gpio_GetData(_1wd_pin.port,_1wd_pin.pins,&result); delay_us(STANDARD_SPEED_F); return result; } void OWWriteByte(uint8_t data,PinMap _1wd_pin) { uint8_t loop; // Loop to write each bit in the byte, LS-bit first for (loop = 0; loop < 8; loop++) { OWWriteBit(data & 0x01,_1wd_pin); // shift the data byte for the next bit data >>= 1; } } uint8_t OWReadByte(PinMap _1wd_pin) { uint8_t loop,result; for(loop = 0; loop < 8; loop++) { // shift the result to get it ready for the next bit result >>= 1; // if result is one, then set MS bit if(OWReadBit(_1wd_pin)) result|= 0x80; } return result; } /* * Write a 1-Wire data byte and return the sampled result. */ uint8_t OWTouchByte(uint8_t data,PinMap _1wd_pin) { uint8_t loop,result; for(loop = 0; loop < 8; loop++) { // shift the result to get it ready for the next bit result >>= 1; // If sending a '1' then read a bit else write a '0' if(data & 0x01) { if(OWReadBit(_1wd_pin)) result |= 0x80; } else OWWriteBit(0,_1wd_pin); // shift the data byte for the next bit data >>= 1; } return result; } void OWBlock(uint8_t *data, uint8_t data_len,PinMap _1wd_pin) { uint8_t loop; for(loop = 0; loop < data_len; loop++) { data[loop] = OWTouchByte(data[loop],_1wd_pin); } }
Hello!
I was able to find two potential problems:
1. Configuring SysTick to interrupt every 1us could hang the program because the interrupt would be too often for it to do much else. Try to make #define TICKS (26000000u/100000u) and adjust the STANDARD_SPEED defines accordingly considering that now the timer ticks every 10us instead of every 1us.
2. You should enable the input driver for the GPIO pin you are using by calling adi_gpio_InputEnable.
Regards,
Andrei.
Just a point to add on Andrei's comments. While the MCU is driving the bus, Output Enable should be True and while sampling the bus, Output Enable should be False & Input Enable should be True.
Regards,
Rajalakshmi
a 1us second interrupt is required to use this protocol according to https://www.maximintegrated.com/en/app-notes/index.mvp/id/126, some delays of the standard speed are not multiples of 10us. How these delays could be modified?
I think the 1us time delay is only required for overdrive mode. I believe that it can work with 10us delay.
This tutorial on 1-wire mentions the time intervals that can be used in 1-wire implementation.
https://www.maximintegrated.com/en/products/1-wire/flash/overview/index.cfm
You can change:
STANDARD_SPEED_A 1
STANDARD_SPEED_B 7 (or 8 if the slave is particularly slow)
STANDARD_SPEED_E 1 (or 0 if the slave is particularly fast)
STANDARD_SPEED_F 5 (or 6 if STANDARD_SPEED_E is 0)
And the rest are evenly divided by 10.
The critical part is the STANDARD_SPEED_E because in the tutorial the master needs to read at exactly 15us. If it does not work with 1 or 0 try changing #define TICKS (26000000u/200000u) and use
STANDARD_SPEED_A 2
STANDARD_SPEED_B 12
STANDARD_SPEED_E 1
and the rest are divided by 5.
Hope this helps.
All the best,
Andrei
I think the 1us time delay is only required for overdrive mode. I believe that it can work with 10us delay.
This tutorial on 1-wire mentions the time intervals that can be used in 1-wire implementation.
https://www.maximintegrated.com/en/products/1-wire/flash/overview/index.cfm
You can change:
STANDARD_SPEED_A 1
STANDARD_SPEED_B 7 (or 8 if the slave is particularly slow)
STANDARD_SPEED_E 1 (or 0 if the slave is particularly fast)
STANDARD_SPEED_F 5 (or 6 if STANDARD_SPEED_E is 0)
And the rest are evenly divided by 10.
The critical part is the STANDARD_SPEED_E because in the tutorial the master needs to read at exactly 15us. If it does not work with 1 or 0 try changing #define TICKS (26000000u/200000u) and use
STANDARD_SPEED_A 2
STANDARD_SPEED_B 12
STANDARD_SPEED_E 1
and the rest are divided by 5.
Hope this helps.
All the best,
Andrei
Thank you for your help. Feel free test the code. Once I tested It I will re-post it to be used.