{"id":3126,"date":"2025-01-02T14:12:11","date_gmt":"2025-01-02T14:12:11","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3126"},"modified":"2025-01-02T14:12:13","modified_gmt":"2025-01-02T14:12:13","slug":"creating-a-library-for-pcf8591-ad-da-module-part-2-building-the-library","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3126","title":{"rendered":"Creating a Library for PCF8591 AD\/DA module Part 2: Building the Library"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957.webp\" alt=\"\" class=\"wp-image-3127\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957.webp 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957-300x300.webp 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957-150x150.webp 150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957-768x768.webp 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957-750x750.webp 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957-400x400.webp 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/effc81f2-def4-45e8-9f29-55c129eca957-250x250.webp 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In the second part of the PCF8591 library, we shall build the library to interface the module with STM32F4.<\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Creating the header and source file.<\/li>\n\n\n\n<li>Developing the header file.<\/li>\n\n\n\n<li>Developing the source file.<\/li>\n\n\n\n<li>Testing the library.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">4. Creating the Header and Source File:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>After the project has been generated by STM32CubeMX within STM32CubeIDE, we shall add new source file and header file.<\/p>\n\n\n\n<p>Right click on Src folder and add new source file as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"486\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-1024x486.jpg\" alt=\"\" class=\"wp-image-2972\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-1024x486.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-300x142.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-768x364.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-1536x729.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-2048x972.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-1150x546.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-750x356.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-400x190.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/2024-11-07_07-03-43-250x119.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Give a name for the source file, we shall name it as PCF8591.c as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"734\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-1024x734.jpg\" alt=\"\" class=\"wp-image-3128\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-1024x734.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-300x215.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-768x550.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-1150x824.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-750x538.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-400x287.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02-250x179.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-43-02.jpg 1172w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In similar manner, right click on Inc folder and add new header file with name of PCF8591.h.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Developing the Header File:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Open PCF8591.h then declare the following enumeration to handle the single ended conversion as following:<\/p>\n\n\n\n<p>First, include the stdint header file:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;stdint.h&quot;<\/pre><\/div>\n\n\n\n<p>Then the enumeration:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">typedef enum\n{\n\tCH0=0,\n\tCH1=1,\n\tCH2=2,\n\tCH3=3\n\n}ADC_ChannelTypedef;<\/pre><\/div>\n\n\n\n<p>This is taken from the datasheet as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"979\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-979x1024.jpg\" alt=\"\" class=\"wp-image-3129\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-979x1024.jpg 979w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-287x300.jpg 287w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-768x803.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-1469x1536.jpg 1469w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-1150x1202.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-750x784.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-400x418.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56-250x261.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2024-12-29_07-04-56.jpg 1534w\" sizes=\"(max-width: 979px) 100vw, 979px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Since the module supports the differential mode, we shall declare the following enumeration to handle the differential reading as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">typedef enum\n{\n\tDiff_AN0_AN1=0,\n\tDiff_AN2_AN3=1\n}DAC_DiffTypedef;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, declare the following function prototypes:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void PCF8591_SetAddress(uint8_t address);<\/pre><\/div>\n\n\n\n<p>This function shall change the address of the module if there were changes to the address pins as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"700\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-1024x700.jpg\" alt=\"\" class=\"wp-image-3130\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-1024x700.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-300x205.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-768x525.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-1536x1050.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-1150x786.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-750x513.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-400x273.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05-250x171.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-51-05.jpg 1940w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, single ended read function as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t ReadADC_SingleEnded(ADC_ChannelTypedef channel);<\/pre><\/div>\n\n\n\n<p>The function measure single channel of the ADC and returns the measured values and take the channel number.<\/p>\n\n\n\n<p>In similar manner, the differential function as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t ReadADC_Differential(DAC_DiffTypedef channel);<\/pre><\/div>\n\n\n\n<p>It will return the measured differential value and takes which channel.<\/p>\n\n\n\n<p>Finally, set DAC value function as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void Set_DAC_Value(uint8_t DACValue);<\/pre><\/div>\n\n\n\n<p>The function shall set the DAC output.<\/p>\n\n\n\n<p>Hence, the entire header file as following:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#ifndef INC_PCF8591_H_\n#define INC_PCF8591_H_\n\n#include &quot;stdint.h&quot;\n\n\ntypedef enum\n{\n\tCH0=0,\n\tCH1=1,\n\tCH2=2,\n\tCH3=3\n\n}ADC_ChannelTypedef;\n\n\ntypedef enum\n{\n\tDiff_AN0_AN1=0,\n\tDiff_AN2_AN3=1\n}DAC_DiffTypedef;\n\n\nvoid PCF8591_SetAddress(uint8_t address);\n\nuint8_t ReadADC_SingleEnded(ADC_ChannelTypedef channel);\n\nuint8_t ReadADC_Differential(DAC_DiffTypedef channel);\n\n\nvoid Set_DAC_Value(uint8_t DACValue);\n\n\n\n#endif \/* INC_PCF8591_H_ *\/<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Developing the Source File:<\/h2>\n\n\n\n<p>Open PCF8591.c source file.<\/p>\n\n\n\n<p>We start by including the following header file:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;PCF8591.h&quot;\n#include &quot;i2c.h&quot;<\/pre><\/div>\n\n\n\n<p>Next, declare a variable to hold the address of the PCF8591 as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">static uint8_t PCF8591_Addr = 0x48&lt;&lt;1;<\/pre><\/div>\n\n\n\n<p>The shift to left is needed to add the read\/write bit as needed by the I2C standard.<\/p>\n\n\n\n<p>Note: This is for STM32F4Cube HAL API. Other MCU might do that in the API itself.<\/p>\n\n\n\n<p>For changing the address of the module:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void PCF8591_SetAddress(uint8_t address)\n{\n\tPCF8591_Addr=address&lt;&lt;1;\n}<\/pre><\/div>\n\n\n\n<p>For reading single ended channel function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t ReadADC_SingleEnded(ADC_ChannelTypedef channel)\n{\n\tuint8_t tempData[2];\n\n\tuint8_t dataWriteTemp=0x40|channel;\n\n\tHAL_I2C_Mem_Read(&amp;hi2c1, PCF8591_Addr, dataWriteTemp, 1, tempData, 2, 100);\n\n\treturn tempData[1];\n\n}<\/pre><\/div>\n\n\n\n<p>First, declare buffer of two byte to hold the read bytes.<\/p>\n\n\n\n<p>Variable to hold the data to be written which is the control byte ored with the channel.<\/p>\n\n\n\n<p>Read the memory address of 0x40|channel and return the second byte of the buffer since the first byte is dummy byte.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In similar manner, for differential channel reading:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t ReadADC_Differential(DAC_DiffTypedef channel)\n{\n\tuint8_t controlByte = channel; \/\/ 0x00: AIN0-AIN1, 0x01: AIN2-AIN3\n\tuint8_t dummyRead, adcValue;\n\n\t\/\/ Send control byte to configure differential mode\n\tHAL_I2C_Master_Transmit(&amp;hi2c1, PCF8591_ADDR, &amp;controlByte, 1, 100);\n\n\t\/\/ Perform a dummy read to settle the ADC\n\tHAL_I2C_Master_Receive(&amp;hi2c1, PCF8591_ADDR, &amp;dummyRead, 1, 100);\n\n\t\/\/ Read actual ADC value\n\tHAL_I2C_Master_Receive(&amp;hi2c1, PCF8591_ADDR, &amp;adcValue, 1, 100);\n\n\treturn adcValue; \/\/ Return the ADC value (0\u2013255)\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>For setting the DAC value:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void Set_DAC_Value(uint8_t DACValue)\n{\n\n    uint8_t data[2];\n    data[0] = 0x40;  \/\/ Control byte: Enable DAC\n    data[1] = DACValue; \/\/ Digital value (0 to 255)\n\n    HAL_I2C_Master_Transmit(&amp;hi2c1, PCF8591_Addr, data, 2, 100);\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the source file as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;PCF8591.h&quot;\n#include &quot;i2c.h&quot;\n\nstatic uint8_t PCF8591_Addr = 0x48&lt;&lt;1;\n\n\n\nvoid PCF8591_SetAddress(uint8_t address)\n{\n\tPCF8591_Addr=address&lt;&lt;1;\n}\n\n\nuint8_t ReadADC_SingleEnded(ADC_ChannelTypedef channel)\n{\n\tuint8_t tempData[2];\n\n\tuint8_t dataWriteTemp=0x40|channel;\n\n\tHAL_I2C_Mem_Read(&amp;hi2c1, PCF8591_Addr, dataWriteTemp, 1, tempData, 2, 100);\n\n\treturn tempData[1];\n\n}\n\n\nuint8_t ReadADC_Differential(DAC_DiffTypedef channel)\n{\n\tuint8_t controlByte = channel; \/\/ 0x00: AIN0-AIN1, 0x01: AIN2-AIN3\n\tuint8_t dummyRead, adcValue;\n\n\t\/\/ Send control byte to configure differential mode\n\tHAL_I2C_Master_Transmit(&amp;hi2c1, PCF8591_ADDR, &amp;controlByte, 1, 100);\n\n\t\/\/ Perform a dummy read to settle the ADC\n\tHAL_I2C_Master_Receive(&amp;hi2c1, PCF8591_ADDR, &amp;dummyRead, 1, 100);\n\n\t\/\/ Read actual ADC value\n\tHAL_I2C_Master_Receive(&amp;hi2c1, PCF8591_ADDR, &amp;adcValue, 1, 100);\n\n\treturn adcValue; \/\/ Return the ADC value (0\u2013255)\n\n}\n\n\n\nvoid Set_DAC_Value(uint8_t DACValue)\n{\n\n    uint8_t data[2];\n    data[0] = 0x40;  \/\/ Control byte: Enable DAC\n    data[1] = DACValue; \/\/ Digital value (0 to 255)\n\n    HAL_I2C_Master_Transmit(&amp;hi2c1, PCF8591_Addr, data, 2, 100);\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>That all for the source file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Testing the Library;<\/h2>\n\n\n\n<p>Before testing the library, connect the DAC output of the module to the AIN0 of the module since we shall use DAC to read the voltage generated by the DAC.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Open the main.c file.<\/p>\n\n\n\n<p>In user code begin Includes, include the following header files:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;PCF8591.h&quot;\n#include &quot;stdio.h&quot;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In user code begin PV, declare the following variables:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint8_t adc_data;\n\nuint8_t uart_buffer[100];<\/pre><\/div>\n\n\n\n<p>In while 1 loop:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\t\tuint16_t len;\n\n\t    len=sprintf(uart_buffer,&quot;------------------\\r\\n&quot;);\n\t    HAL_UART_Transmit(&amp;huart2, &amp;uart_buffer, len, 100);\n\n\t  \tSet_DAC_Value(128);\n\n\t\tadc_data=ReadADC_SingleEnded(CH0);\n\n\t\tlen= sprintf(uart_buffer,&quot;ADC Value = %d\\r\\n&quot;,adc_data);\n\t\tHAL_UART_Transmit(&amp;huart2, &amp;uart_buffer, len, 100);\n\t\tHAL_Delay(2000);\n\n\t  \tSet_DAC_Value(255);\n\t\tadc_data=ReadADC_SingleEnded(CH0);\n\t\tlen= sprintf(uart_buffer,&quot;ADC Value = %d\\r\\n&quot;,adc_data);\n\t\tHAL_UART_Transmit(&amp;huart2, &amp;uart_buffer, len, 100);\n\t\tHAL_Delay(2000);\n\n\t  \tSet_DAC_Value(128);\n\t\tadc_data=ReadADC_SingleEnded(CH0);\n\t\tlen= sprintf(uart_buffer,&quot;ADC Value = %d\\r\\n&quot;,adc_data);\n\t\tHAL_UART_Transmit(&amp;huart2, &amp;uart_buffer, len, 100);\n\t\tHAL_Delay(2000);\n\n\t  \tSet_DAC_Value(0);\n\t\tadc_data=ReadADC_SingleEnded(CH0);\n\t\tlen= sprintf(uart_buffer,&quot;ADC Value = %d\\r\\n&quot;,adc_data);\n\t\tHAL_UART_Transmit(&amp;huart2, &amp;uart_buffer, len, 100);\n\t\tHAL_Delay(2000);<\/pre><\/div>\n\n\n\n<p>The len variable to hold the number of characters to be transmitted by the UART.<\/p>\n\n\n\n<p>First, set the DAC to 128, then read CH0 and print the results.<\/p>\n\n\n\n<p>In similar manner, set the DAC to 255, then 128 then 0.<\/p>\n\n\n\n<p>Save the project, build it and run it on your board as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"28\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-1024x28.png\" alt=\"\" class=\"wp-image-2982\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-1024x28.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-300x8.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-768x21.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-1536x43.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-1150x32.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-750x21.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-400x11.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image-250x7.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/11\/image.png 1734w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Open your favourite serial terminal application, set the baudrate to be 115200 and you should get the following:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"871\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-1024x871.jpg\" alt=\"\" class=\"wp-image-3131\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-1024x871.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-300x255.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-768x653.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-1150x978.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-750x638.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-400x340.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59-250x213.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/01\/2025-01-02_16-32-59.jpg 1284w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The results are near the set value.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the second part of the PCF8591 library, we shall build the library to interface the module with STM32F4. In this guide, we shall cover the following: 4. Creating the Header and Source File: After the project has been generated by STM32CubeMX within STM32CubeIDE, we shall add new source file and header file. Right click [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-3126","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3126"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3126"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3126\/revisions"}],"predecessor-version":[{"id":3132,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3126\/revisions\/3132"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}