Есть несколько проблем с этой программой. Большая часть этого кода зависит от поведения undefined . Объединения также являются UB, если используются для наложения имен, даже если почти все компиляторы C имеют тенденцию допускать это, но если вы используете объединение, я все же предпочел бы использовать char[]
для массива, используемого для псевдонима. Как упоминалось в комментариях, "Hi Dave!\r\n";
фактически занимает 11 байтов с нулевым символом. Безопаснее использовать uint8_t myData[] = "Hi Dave!\r\n";
или const * uint8_t = "Hi Dave!\r\n";
и избавить себя от проблем.
Вторая проблема заключается в том, что strlen
не может корректно работать с двоичными данными. strlen
работает путем поиска первого появления нулевого символа в строке , поэтому он не применим для двоичных данных. Если вы передадите значение с плавающей запятой, которое имеет единственный нулевой байт в его представлении IEEE 754, оно отметит конец этой «строки».
Проще говоря, ваша функция должна быть объявлена как fsp_err_t uart_write(const char * msg, size_t msg_len);
и вызывается с помощью uart_write(data_array, sizeof data_array);
. Если вы хотите передавать сообщения переменного размера через UART, вам также необходимо определить определенный протокол связи, то есть создать сообщение, которое можно будет однозначно проанализировать. Скорее всего, это будет означать: 1) некоторую готовность ie в начале, 2) длину передаваемых данных, 3) фактические данные, 4) cr c - но это выходит за рамки этого вопроса.
Итак, strlen
не сообщит вам длину данных, вы сами передадите его функции, и вам вообще не нужны объединения. Если вы решите не сериализовать данные должным образом (например, используя protobuf или какой-либо другой протокол), вы можете просто передать указатель на структуру функции, т.е. вызвать вышеупомянутый uart_write((char*)&some_struct, sizeof some_struct);
, и он будет работать как если бы вы передали массив.
Обратите внимание, что char
в этом случае не означает «символ ascii» или «символ в строке». Суть использования char*
заключается в том, что это единственный указатель, которому разрешено использовать псевдоним других указателей . Итак, вы получаете указатель на свою структуру (&str
), преобразуете его в char*
и передаете его функции, которая затем может читать свое представление в памяти. Я знаю, что R_SCI_UART_Write
, вероятно, генерируется вашей IDE, и, к сожалению, в этих блоках часто используется uint8_t*
вместо char*
, поэтому вам, вероятно, в какой-то момент придется выполнить приведение к uint8_t*
.