Managing data between MATLAB and C#

Often, we will want to examine data generated on the board using MATLAB or export data from MATLAB (such as filter coefficients in Lab 3) to use in our C code.

Moving data from MATLAB to C.#

The tree.png image will be used as the data payload in some subsequent lab exercises.

It is a 128x128 binary image (16,384 bits or 512 32-bit words). In MATLAB, we can load this file as a matrix using ‘imread’ and display it using ‘imshow’:

tree = imread('tree.png');
imshow(tree);

There are two main ways we can load data like this on the STM32 board:

  1. Use STM32CubeProg or similar software to directly load the data to an appropriate section of the processor’s memory. This method is appropriate for large chunks of data like audio or video files.

  2. Format the data into text (usually hexadecimal) and directly initialize a variable with the data in a .c or .h file. This method is appropriate for smaller chunks of data like the filter coefficients or the relatively small tree.png, and is what we will use for the lab exercises.

In MATLAB, the ‘sprintf’ command is a convenient way to format data into text so that it can be directly copied into C code. As an example, consider the following MATLAB code to format one period of a cosine with with \(\omega_0 = \frac{\pi}{8}\)

data = cos(0 : pi/4 : 7*pi/4);
str = sprintf('%.8g,',data);
>> str
'1,0.70710678,6.123234e-17,-0.70710678,-1,-0.70710678,-1.8369702e-16,0.70710678,'

In this format the data can be easily copied into a variable declaration in a .c file.

float32_t data[8] = {1,0.70710678,6.123234e-17,-0.70710678,-1,-0.70710678,-1.8369702e-16,0.70710678};

The ‘%.8g’ format is adequate for single precision floating point values, but is not ideal for binary data like the tree image. Instead, we can use ‘%x’ for hexadecimal.

Before formatting the data using sprintf, we must orgainize the data into appropriately sized words with the correct endianness.

  1. Convert the image into a vector of zeros and ones. For this example, we will map white pixels to 0 and black pixels to one:

    tree = 1 - imread('tree.png');
    data = reshape(tree,[1,128^2]);
    
  2. Convert the data from the MATLAB default (double) to a string of zeros and ones as required by the bin2dec function:

    data_bin = sprintf('%i',data);
    
  3. Group the data into words that are each 32 bits. To change the endianness, flip the array horizontally with ‘fliplr’.

    data_32bit = fliplr(reshape(data_bin,[32,512])');
    
  4. Use sprintf to format the data.

    To print all of the data on one line, use

    sprintf('0x%x,',bin2dec(data_32bit))
    

    Alternatively print the values across multiple lines (in this case 16 words per line).

    sprintf([repmat('0x%x,',[1,16]) '\n'],bin2dec(data_32bit))
    

The resulting variable declaration in C would be:

uint32_t tree[512] = {
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x1c600,
0x0,0x0,0x0,0x1e100,0x0,0x0,0x0,0x1e000,0x0,0x0,0x0,0x1f080,0x0,0x0,0x0,0x3880,
0x0,0x0,0x0,0x1880,0x0,0x0,0x0,0xc80,0x0,0x0,0x0,0x680,0x0,0x0,0x0,0x680,
0x0,0x0,0x0,0x4680,0x0,0x0,0x0,0x6680,0x0,0x0,0x0,0x680,0x0,0x0,0x0,0xc0e80,
0x0,0x0,0x0,0x40e80,0x0,0x0,0x0,0x20680,0x0,0x0,0x0,0x10680,0x0,0x0,0x0,0x8680,
0x0,0x0,0x0,0x680,0x0,0x0,0x0,0x680,0x0,0x0,0x0,0x680,0x0,0x0,0x0,0x680,
0x0,0x0,0x0,0x600680,0x0,0x0,0x0,0x104680,0x0,0x0,0x0,0x82680,0x0,0x0,0x0,0x41680,
0x0,0x1c00000,0x0,0x20e80,0x0,0x1e00000,0x0,0x10680,0x0,0x3e00000,0x0,0x8680,0x30000000,0x83c00004,0x1,0x4680,
0x20000000,0x8600200c,0x1,0x680,0x40000000,0xc002008,0x0,0x680,0x8f000000,0x18404010,0x0,0x680,0xff000000,0x1c408000,0x0,0x380,
0xff000000,0x9801038c,0x0,0x802180,0x86000000,0x78004399,0x0,0x4010c0,0xc00000,0x30004793,0x0,0x200860,0x8c00000,0x63818fa6,0x21,0x100460,
0x19008000,0x67011c2c,0x71,0x80260,0x22018c00,0x66081838,0xd2,0x40160,0xfff20e00,0x6c0c1f3f,0xf4,0x200e0,0x21b00,0x78021a31,0x68,0x810c60,
0x80009e00,0x7f82d030,0x22,0x38c08c60,0x9c01bc00,0x60807030,0x62,0x3c004260,0x3c626000,0xc0383230,0x6c,0x3c202160,0x3c40e040,0x87f83230,0xc9,0x3c1020e0,
0x7880c040,0xff86260,0x183,0x6082060,0xe100cc80,0x1c39c1ec,0x18e,0x3ff2060,0xfe039900,0xf801818d,0x18f,0x1ff9060,0x80073200,0xf70f0303,0x19f,0x1c860,
0x1e60180,0x11e0603,0x1b0,0x26463,0x20c0180,0x300c06,0x800001fe,0x4363f,0xfffffc00,0x7ffffff,0xe00001c8,0x201f9f,0xfffffc00,0x4fffffff,0xf0000184,0x400fc3,
0x3800180,0xd8030002,0x38000383,0x18000e0,0x11fc0100,0x3fc1f841,0x1c000670,0x1801e60,0xb007c200,0x6200ffe0,0x8ffffe00,0x21ff,0x4003e360,0xc1082707,0xe0000000,0xc01f,
0x23026110,0xe8fc1bff,0xffffffff,0x18007,0x13b3088,0x1c0019ff,0x3fffffff,0x3,0xfed88c,0xc38007,0x0,0x600,0x1fe4c04,0xe0ff80c4,0x1fffffff,0x100603,
0x3f180e00,0x71ff84c4,0xf0000000,0x18010f,0x7e010bc0,0x3be30808,0xe3fff800,0x400bf,0xc41089f0,0x9e0c1e7f,0x87fffe0f,0x38073,0x83f06478,0xe2c46ff,0xc000700,0x43e0,
0x1e00236c,0x1760c1c0,0x180003e0,0x2600,0xfe000338,0x1bffffff,0xb00001ff,0x4001c03,0xe240010,0xf0038007,0xe00000e1,0xf80181f,0xc0000,0xd801c063,0xc0000060,0x40303f,
0xf0080000,0x68f8fe61,0x30,0x207063,0xffffe000,0x3100ff80,0x18,0x1fc060,0x5c011000,0x1a313bb8,0x1c,0xc0060,0x4e00c800,0x1ff919f8,0x1e,0x181060,
0x37f04600,0x7f90cf8,0x1b,0x301060,0xa3fc0600,0x80380639,0x19,0x702060,0xe0000,0xc601f302,0x18,0x3c040e0,0x8b0000,0xf20411c6,0x18,0x7808160,
0x64cf0000,0xf00801e0,0x30,0x3c010660,0x22460000,0xff9f0160,0xf0,0x78220060,0x19000000,0xdcf10130,0x1e0,0x78c23060,0x800000,0xce7f1c1e,0x1e0,0x78c260c0,
0x800000,0xc731fd0f,0x1e0,0x100201c0,0x80000000,0xf310fc89,0x80,0x40300,0xc0000000,0xc9ce18cc,0x0,0x80600,0x78000000,0x66e04002,0x0,0x100e00,
0x78000000,0x74706003,0x0,0x200a00,0x78000000,0x30202000,0x0,0x401a00,0x30000000,0x38000004,0x0,0x803a00,0x0,0x3fb80002,0x0,0x1004a00,
0x80000000,0x37c00001,0x0,0x1008a00,0x80000000,0x30e70001,0x0,0x10a00,0x0,0x307f0000,0x0,0x20a00,0x0,0x703f0000,0x0,0x20a00,
0x0,0x78070000,0x0,0xa00,0x0,0x78000000,0x0,0xa00,0x0,0x70000000,0x0,0x40a00,0x0,0x0,0x0,0x81a00,
0x0,0x0,0x0,0x103a00,0x0,0x0,0x0,0x304a00,0x0,0x0,0x0,0x208a00,0x0,0x0,0x0,0x10a00,
0x0,0x0,0x0,0x20a00,0x0,0x0,0x0,0x40a00,0x0,0x0,0x0,0x80a00,0x0,0x0,0x0,0x100a40,
0x0,0x0,0x0,0x2008c0,0x0,0x0,0x0,0x601800,0x0,0x0,0x0,0xc03a00,0x0,0x0,0x0,0x4a00,
0x0,0x0,0x0,0x38a00,0x0,0x0,0x0,0x40a00,0x0,0x0,0x0,0x80a00,0x0,0x0,0x0,0x101a00,
0x0,0x0,0x0,0x303200,0x0,0x0,0x0,0x207200,0x0,0x0,0x0,0x1e200,0x0,0x0,0x0,0x3c000,
0x0,0x0,0x0,0x3c200,0x0,0x0,0x0,0x18200,0x0,0x0,0x0,0x200,0x0,0x0,0x0,0x400,
0x0,0x0,0x0,0x1800,0x0,0x0,0x0,0x1800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

Moving data from C to MATLAB#

The STM32CubeIDE has a memory browser feature which can be used to easily locate and export a chunk of memory while in debug mode.

  1. Verify that the data is in memory using either the ‘variables’ or ‘expressions’ view.

  2. Open the memory browser (Window → Show view → Memory Browser).

  3. Identify the address of the beginning of the data you want to access in the memory browser. For example, if using the array above enter tree or &tree[0], and you will see the associated address listed in hexadecimal.

  4. Identify the address of the last byte of memory you want to extract using the same procedure (e.g. type &tree[512] in the memory browser).

  5. click the Export icon in the memory browser. Choose the appropriate memory addresses, ‘RAW Binary’ as the data type, and a filename, then click okay

  6. Load the exported data into MATLAB using ‘fread’:

    fid = fopen('C:\...\data.bin');
    data = fread(fid,16384,'bit1'); 
    fclose(fid)