Adom Kwabena

Electrical Engineer, Maker, Tinkerer

Writing Embedded Drivers


Embedded drivers are the glue between software and hardware, and are a very important part of embedded systems. In other words embedded drivers enable us to easily talk to chips using interfaces like TWI (Two Wire Interface) because unfortunately chips don’t speak English – pun intended. Being able to write simple embedded drivers is a good skill to have although platforms with good libraries like Arduino exist. You don’t want to be stuck on a project because you can’t find a library for a critical chip in your design.¬† I’ll use the HDC1000 chip from Texas Instruments as an example for writing embedded drivers. Let’s dive in.

Reading The Datasheet

Datasheets contain all the technical information you need to write your embedded driver. Reading datasheets is a very important engineering skill. Datasheets are organised in sections which describe various aspects of the chip. The first page of a datasheet usually contains the features, applications and a basic description of the chip. From this page we get to know the chip and its major applications. Now we know that the HDC1000 is a temperature and humidity sensor with an I2C interface. We also get a schematic of a typical application which is very useful.

Application Circuit

Section 6 of the datasheet contains the pin information of the HDC1000, this tells us the function of each pin and its location on the chip. This info is key when we build the physical circuit. Section 7 of the HDC1000 datasheet describes the electrical specifications of the chip. In section 7.1 we find the absolute maximum ratings of the chip. It is very important that we don’t exceed the parameters listed in the absolute maximum ratings to avoid damaging our chip. Electrical characteristics, I2C interface characteristics, a timing diagram and characteristic graphs are also found in section 7 of the HDC1000 datasheet.

Absolute Maximum Ratings

We can find a detailed description of the workings of the chip along with a block diagram in section 8 of the datasheet. From the functional block diagram we can see that there are two sensing elements, one for relative humidity and one for temperature. The sensors are multiplexed into an ADC which is controlled by registers and logic. The registers and logic are connected to calibration coefficients which are one time programmable. And finally there is an I2C block which enables us to interface/talk to this chip with pretty much any microcontroller.

Functional Block Diagram

Using The Datasheet

Here comes the fun part. Let’s get to know the individual registers which control the chip and how to properly configure them. At this point I usually pull out a piece of paper and take some notes to simplify programming.¬† There are 8 registers inside the HDC1000, but we need to bother about 3 for now. The configuration register is for setting up the chip. The configuration register controls the order of readout and resolution of our temperature and humidity measurements. The temperature and humidity registers contain our measured values. In summary this is what we need to do in software:

  1. Configure the chip for readout by setting the acquisition mode and selecting the measurement resolution.
  2. Trigger a measurement.
  3. Wait for the measurement to complete.
  4. Read the output data.

Step 1 has to be done at least once, but steps 2-4 must be repeated for every measurement. At this point we can start writing the driver using our datasheet as a reference.

Writing The Header File

We need a header file for definitions and function prototypes, for this example we will create a file called “hdc1000.h”. So now we simply need a bunch of functions to do the following:

  • Abstract I2C functionality; reading and writing to the chip.
  • Provide functions for HDC1000 register access.
  • Provide functions for acquiring temperature and humidity data.

We will define the registers of the HDC1000 so we can use them in our functions.

We will also define masks for setting bits in the configuration register

Lastly we write our function prototypes

Writing The Source File

Let’s create a file called “hdc1000.c” to implement our functions in. Firstly, let’s include the necessary header files. The first line gives us access to microchip’s I2C driver for 8 bit PICs. The second line provides us with function prototypes for our code.

Instead of using the I2C functions directly let’s create a wrapper function to abstract the native I2C functions of the MCU. This is a nice and easy way of enhancing portability. Below is a function for reading data from the HDC1000. The code for writing data to the HDC1000 is very similar to this.

Next we need functions to access registers in the HDC1000 sensor. We need to let the chip know which register we want to access. We do this by writing the address of the register we want to access before we perform any read or write transaction. The code for writing data to a register is shown below. It is similar to the code for reading data from a register. You’re probably wondering why there’s a delay before reading data from the chip. Doing this allows us to simplify the functions for reading temperature and humidity by just calling this one function. We will be reading temperature and humidity data more often than other registers. Hence there will be a small performance penalty of 8 milliseconds when reading data from other registers!

Lastly, let’s look at the functions for reading the temperature and humidity. All we have to do is call the “hdc1000_get_reg” function and pass the address of the temperature or humidity register. You can implement the functions below as macros to improve performance.

Using The Driver

It’s time to enjoy our efforts. Let’s add our source and header files to a project in order to use the driver. We have to include the header file in our main file to access the functions provided. To configure/initialize the chip we can use the code below.

After initialization we can trigger measurements at will. All measurements are in a raw format. The datasheet provides us with formulas for calculating the temperature and humidity using the raw data.

Here is a serial output of our demo viewed with pyserial in a python script.

Serial Output

Porting To Other Platforms

I have personally ported this driver to the MSP430 with minimal modifications. The major modification needed is to replace the code in the “hdc1000_read” and “hdc1000_write” functions with the I2C functions of the platform you’re porting to.


You can find the source code along with documentation  here. Looking to add an LCD display to the demo? Check out my earlier post.


Interfacing With HD44780 Displays


Sourcing Electronic Components In Ghana


  1. Kwaku Addo

    Great work, Adom. Keep the posts coming.

  2. Yaw Obeng

    Very informative. Glad I found this.

Leave a Reply

Your email address will not be published. Required fields are marked *

Powered by WordPress & Theme by Anders Norén