2012-03-22 4 views
3

Я пишу код для протокола Modbus, который работает на контроллере MSP430. Буфер ответа (глобальный) представляет собой массив из 8-битных данных, через который ответ на обработанный запрос должен быть отправлен по последовательному UART. Теперь моя проблема в том, что генерируемый ответ имеет комбинацию разных типов данных. i.e uint8, uint32, float. Как отправить эти данные с помощью глобального буфера ответов?Копирование содержимого буфера разных типов данных

Для float, я пробовал использовать memcpy, и это, кажется, работает нормально. Есть ли лучший и эффективный способ? Потому что размер кадра большой (скажем, 20-30 байтов). Вот демонстрация того, что я пытался сделать

int main() 
{ unsigned char buff[8]; //Global buffer 

float temp[2]; //temp buffer to store response values 

temp[0] = 0x00ef2212; 

memcpy(buff, temp, 8); 

printf("buff[0]= %u \n buff[1]= %u\n buff[2] = %u\n buff[3]= %u\n", buff[0],buff[1],buff 
[2],buff[3]); 

return 0; 
} 

ответ

1

С литьем и назначением. Например.

uint8 *globalbuf; 
uint32 myval; 
*(uint32*)globalbuf = myval; 

копии myval в первые 4 байта globalbuf.

Опасайтесь проблем с выравниванием: на вашей платформе может быть незаконно или дорогостоящим назначать или считывать значения на/из адресов, которые не являются целыми кратными размеру этого типа. Например, адрес 0,4,8 и т. Д. В порядке, чтобы положить uint32.

Это предполагает, что ваша globalbuf начинается на хорошем круглый адрес ..

+0

memcpy для большинства случаев использования достаточно эффективен. я бы собрал весь ответ, а затем сделал один memcpy. Использование typecasting * (* globalbuf) = val было бы таким же эффективным и дорогим, как memcpy, и, как упоминалось в blueshift, вы могли столкнуться с проблемами выравнивания. – keety

+0

На MSP430 uint32, как uint16, должен начинаться с четной границы байта - 16-битный процессор обрабатывает uint32 в двух 16-разрядных фрагментах. Вы можете принудительно назначить цель, указанную globalbuf, на границу uint16, определив объединение массивов uint8 и uint16. Компоновщик поместит эту структуру данных в допустимое местоположение uint16. –

1

простая реализация будет создать структуру ответа и тетср структуры ответа в буфер

struct response { 
    uint8 bytedata; 
    uint32 intdata; 
    float floatdata; 
}; 
memcpy((void *)uartbuffer,(void *)&response,sizeof(response)); 

Примечания: так как это выглядит как и ваша работа над протоколом, endianess может быть уже указана, и вам может понадобиться упаковать элементы в соответствии с конкретным типом endian, и простая memcpy не будет работать, и вам может понадобиться упаковать типы данных.

+0

Проблема с этим решением заключается в том, что ответ может не быть комбинацией одного u8, одного u32 и одного поплавка. Потому что это часть данных кадра ответа (PDU), поэтому переменной длины. Это может быть примерно двадцать восемь, один u32 и 2 поплавки. – OnkarK

+0

@OnkarK Как вы определяете, соответствует ли кадр ответа 4 u8 или только 1 поплавок? – keety

+0

Мне нужно создать кадр ответа для запроса, который у меня есть. Скажем, для запроса на чтение, я собираюсь отправить данные frm reqd в ответ на этот запрос. – OnkarK

0

Как насчет того, чтобы использовать объединение для представления одного и того же диапазона памяти в разные типы данных?

typedef union { 
    unsigned char buff[8]; 
    float temp[2]; 
} un; 

un global_buffer; 
// give global_buffer.buff some data. 
un local_buffer; 

local_buffer = global_buffer; 
// handle local_buffer.temp 
+0

Это невозможно, потому что глобальный буфер уже существует и используется другими вариантами modbus для отправки своих ответов. Как я уже указывал ранее, глобальный буфер представляет собой массив из 253 байтов данных одного байта.Я могу использовать такой союз для создания локального буфера; но затем сохраняется проблема сопоставления его с массивом u8. У меня нет никакой прав для изменения структуры глобального буфера ответов, потому что у Modicon есть возможность сделать modbus только для передачи только 1 байта данных! – OnkarK

+0

вы можете определить свой собственный тип union или struct, а затем наложить его поверх буфера, указав указатель на свой тип и указав ему адрес глобального массива байтов. –

+0

@Ian «наложить его поверх буфера». Можете ли вы разработать бит? – OnkarK

Смежные вопросы