element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Upcycle IoT Design Challenge
  • Challenges & Projects
  • Design Challenges
  • Upcycle IoT Design Challenge
  • More
  • Cancel
Upcycle IoT Design Challenge
Blog Blog #4: HDC1080 with SAM E51
  • Blog
  • Forum
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Upcycle IoT Design Challenge to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: misaz
  • Date Created: 9 Feb 2024 11:34 PM Date Created
  • Views 531 views
  • Likes 8 likes
  • Comments 3 comments
  • SAME51J20A
  • SAM E51 Curiosity Nano Evaluation Kit
  • Upcycle IoT Design Challenge
  • SAM E51
Related
Recommended

Blog #4: HDC1080 with SAM E51

misaz
misaz
9 Feb 2024
Blog #4: HDC1080 with SAM E51

I welcome you to third part of my series as part of Upcycle IoT Design Challenge. Today, I will integrate HDC1080 to SAM E51 project. It was quite challenging for me, because I used SAM E51 microcontroller for first time. Even more challenging it was because HDC1080 implements very specific I2C interface which requires you to let measurement triggering transaction in progress and manually wait for data.

I implemented HDC1080 library like many other libraries which I implemented. I control underlaying I2C driver for communication with chip and also implemented driver UART driver for debugging.

UART

Both UART and I2C are on SAM E51 driven using universal peripheral named SERCOM (Serial communication).

The first step is enabling APB bus clock for the peripheral. I use SERCOM5 for UART:

REG_MCLK_APBDMASK |= MCLK_APBDMASK_SERCOM5;

Then you need to assign GPIOs. Group 0 is port A, Group 1 is port B. PMUX register contains value for two consecutive pins while PINCFG is separate for each pin. Thus, for attaching SERCOM5 (which is alternate function 2) to pins B16 and B17 (which are on Curiosity Nano board connected to on-board debugger), use the following commands.

PORT->Group[1].PMUX[8].bit.PMUXE = 0x02;
PORT->Group[1].PMUX[8].bit.PMUXO = 0x02;
PORT->Group[1].PINCFG[16].bit.PMUXEN = 1;
PORT->Group[1].PINCFG[17].bit.PMUXEN = 1;

Next, you need to allocate and configure one of clock generator which is used for generating baudrate. You need to wait if it is busy. I will use generator number 11. Clock source 6 is internal 48 MHz oscillator and I will not divide it.

while (REG_GCLK_SYNCBUSY & GCLK_SYNCBUSY_GENCTRL11) {}
REG_GCLK_GENCTRL11 = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC(6);

At last, you need to configure SERCOM. You need to reset it, set UART signal polarity and bit order, enable transmitter (and received if used) and finally, set value corresponding to baudrate computed according to formula in datasheet. SERCOM uses multiple clocks, so synchronization between clock domain requires waiting when there is pending transaction after every register write. This is done by waiting for clearing SYNCBUSY bit. Some registers do not need it.

while (REG_SERCOM5_USART_SYNCBUSY) {}
	
REG_SERCOM5_USART_CTRLA = 0;
while (REG_SERCOM5_USART_SYNCBUSY) {}
	
REG_SERCOM5_USART_CTRLA = SERCOM_USART_CTRLA_SWRST;
while (REG_SERCOM5_USART_SYNCBUSY) {}
	
REG_SERCOM5_USART_CTRLA = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE(1);
while (REG_SERCOM5_USART_SYNCBUSY) {}
	
REG_SERCOM5_USART_CTRLB = SERCOM_USART_CTRLB_TXEN;
while (REG_SERCOM5_USART_SYNCBUSY) {}
	
REG_SERCOM5_USART_BAUD = 63019;

REG_SERCOM5_USART_CTRLA |= SERCOM_USART_CTRLA_ENABLE;
while (REG_SERCOM5_USART_SYNCBUSY) {}

That is all.

I2C

I2C is basically very similar. You need to enable APB peripheral clock, configure pin mapping and configure clock. This time you need two clock generators. One for bitrate and one low-frequency for timeouts. I2C configuratiuon is slightly different, but well described in datasheet. Baudrate (or bitrate in case of I2C) calculation is slightly different as well.

I2C transactions are controlled by writing to reg register for initiating transaction, waiting for flags or interrupt, writing command for special I2C operations and writing or reading data register for actual data transfer.

HDC1080 Library

After implementing my own I2C driver, I implemented library. Like in case of my previous libraries, I exposed all features of HDC1080 chip. Library has following functions:

HDC1080_Status HDC1080_Init();
HDC1080_Status HDC1080_Deinit();

HDC1080_Status HDC1080_GetDefaultConfiguration(HDC1080_Configuration* config);
HDC1080_Status HDC1080_GetConfiguration(HDC1080_Configuration* config);
HDC1080_Status HDC1080_SetConfiguration(HDC1080_Configuration* config);

HDC1080_Status HDC1080_TriggerTemperatureAndHumidityConversion();
HDC1080_Status HDC1080_TriggerTemperatureConversion();
HDC1080_Status HDC1080_TriggerHumidityConversion();

HDC1080_Status HDC1080_GetRawTemperature(uint16_t* temperature);
HDC1080_Status HDC1080_GetRawHumidity(uint16_t* humidity);
HDC1080_Status HDC1080_GetRawTemperatureAndHumidity(uint16_t* temperature, uint16_t* humidity);

HDC1080_Status HDC1080_GetTemperature(float* temperature);
HDC1080_Status HDC1080_GetHumidity(float* humidity);
HDC1080_Status HDC1080_GetTemperatureAndHumidity(float* temperature, float* humidity);

HDC1080_Status HDC1080_EnableHeater();
HDC1080_Status HDC1080_DisableHeater();

HDC1080_Status HDC1080_GetBatteryStatus(HDC1080_BatteryStatus* batterySatus);

HDC1080_Status HDC1080_GetManufacturerNumber(uint16_t* manufacturerNumber);
HDC1080_Status HDC1080_GetDeviceId(uint16_t* deviceId);
HDC1080_Status HDC1080_GetSerialNumber(uint64_t* serialNumber);

Simple program for configuring sensor and printing temperature and humidity continuously is following:

int main(void)
{
	HDC1080_Status hStatus;
	
	SystemInit();
	UART_Init();
	UART_PrintString("\r\n");
	
	hStatus = HDC1080_Init();
	checkError(hStatus, "HDC1080_Init");
	
	HDC1080_Configuration config;
	HDC1080_GetDefaultConfiguration(&config);
	hStatus = HDC1080_SetConfiguration(&config);
	checkError(hStatus, "HDC1080_SetConfiguration");
	
    while (1) 
    {
		
		hStatus = HDC1080_TriggerTemperatureAndHumidityConversion();
		checkError(hStatus, "HDC1080_TriggerConversion");
		
		for (volatile int i = 0; i < 50000; i++) {}
		
		float temp = 0;
		float humi = 0;
		hStatus = HDC1080_GetTemperatureAndHumidity(&temp, &humi);
		checkError(hStatus, "HDC1080_Get");
		
		UART_PrintString("TEMP: ");
		UART_PrintFloat2(temp);
		UART_PrintString(" degC\tHUMI: ");
		UART_PrintFloat2(humi);
		UART_PrintString(" %\r\n");
		
		for (volatile int i = 0; i < 1000000; i++) {}
    }
}

Results

And here are the results from serial terminal:

image

Next blog:  Blog #5: Completing up-cycling broken wireless earbuds

  • Sign in to reply

Top Comments

  • shabaz
    shabaz over 1 year ago +1
    Just wondering, does Microchip supply any library code with support for I2C, UART, etc, or does the user have to use register-level operations? Granted that users may prefer to do register-level access…
  • shabaz
    shabaz over 1 year ago in reply to misaz +1
    I see.. Looks like quite a nice microcontroller with interesting peripherals (e.g. dual simultaneous-sampling ADC). I wish Microchip would make more effort to offer a decent way to code for it, since…
  • shabaz
    shabaz over 1 year ago in reply to misaz

    I see.. 

    Looks like quite a nice microcontroller with interesting peripherals (e.g. dual simultaneous-sampling ADC). I wish Microchip would make more effort to offer a decent way to code for it, since it would get irritating fast to have to code down to register level for the basics when prototyping : (

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • misaz
    misaz over 1 year ago in reply to shabaz

    There is whole Atmel start framework which is tightly coupled with code generator, but in my opinion, it is overenginered. I am also curious about its life cycle because it seems that there are no changes since Microchip acquired Atmel.

    Even tutorials on internet are not consistent on recommended way of using SAM MCUs.

    Many peripherals are easy to use like it is in case of 8-bit AVRs, but to be frank, first hours.of using (and debugging) SERCOM was quite painful.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 1 year ago

    Just wondering, does Microchip supply any library code with support for I2C, UART, etc, or does the user have to use register-level operations?

    Granted that users may prefer to do register-level access, but for the times quick prototyping is needed, it would be nice if there were existing functions like i2c_init(), i2c_write(), etc.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube