在我的应用程序中,我定义了一个char数组,它可以采用以下三个选项之一:“okay”,“high”,“low”,然后从串行端口发送到远程设备。我目前的数组大小可以取4个字符加上回车和换行,但是当我必须发送“低”时,我在字符串中得到一个空字符,我担心这会混淆主机终端。
数组定义
char mod1_status_char[6] = {'0','0','0','0','0','0'};
char mod2_status_char[6] = {'0','0','0','0','0','0'};
char mod3_status_char[6] = {'0','0','0','0','0','0'};
switch case语句示例:
void DCOKStatus(uint8_t *ptr_status)
{
uint8_t status = *ptr_status;
switch (status)
{
case 0x00:
strcpy(mod1_status_char, "okay");
strcpy(mod2_status_char, "okay");
strcpy(mod3_status_char, "okay");
break;
case 0x10:
strcpy(mod1_status_char, "okay");
strcpy(mod2_status_char, "okay");
strcpy(mod3_status_char, "low");
break;
}
这是使消息字符串发送的结构
strcpy(MsgStatus_on.descriptor_msg, "$psu_");
MsgStatus_on.address01 = hex_addr[0];
MsgStatus_on.address02 = hex_addr[1];
MsgStatus_on.space01 = 0x20;
strcpy(MsgStatus_on.cmdmsg01, "op_en op1_");
strcpy(MsgStatus_on.statusmsg01, mod1_status_char);
MsgStatus_on.space02 = 0x20;
strcpy(MsgStatus_on.cmdmsg02, "op2_");
strcpy(MsgStatus_on.statusmsg02, mod2_status_char);
MsgStatus_on.space03 = 0x20;
strcpy(MsgStatus_on.cmdmsg03, "op3_");
strcpy(MsgStatus_on.statusmsg03, mod3_status_char);
MsgStatus_on.CR = 0x0D;
MsgStatus_on.LF = 0x0A;
并发送消息
void USARTWrite(char *object, uint32_t size)
{
GPIO_SetBits(GPIOB, GPIO_Pin_1);
char *byte;
for (byte = object; size--; ++byte)
{
USART_SendData(USART1,*byte);
}
当我需要发送“低”时,是否有人能够建议一个好的方法来将数组动态调整为一个字符?
由于
答案 0 :(得分:5)
我认为不需要调用动态大小的数组。 C语言中有两种方法可以动态调整数组大小:使用malloc
或类似方法分配它;或使用C99 VLA。但是在这种情况下,你有不同长度的字符串,当然重要的是按正确的顺序写正确的字节?就个人而言,我更喜欢这样的事情,或许:
char * strings[] = {"okay\r\n", "high\r\n", "low\r\n"};
serial_send(strings[msg_number], strlen(strings[msg_number]));
您不必调用strlen,必须将长度存储在另一个数组中。但即使在最小的嵌入式设备上,与发送串行数据相比,数到6只需要很少的时间。
当然我假设你调用的任何函数实际发送数据,需要一个指针和一个长度。但如果没有,我不会看到动态大小的数组如何帮助。
我认为这里难以回答这个问题的一般问题是你没有真正说出数组的“大小”是什么,或者为什么它与实际写入的字节数有关到串口。
编辑:通过你的额外解释,关键的事情似乎是这个结构,三个单独的字符串被“传入”。不确定将字符串传递给struct意味着什么。如果它目前看起来像这样:
struct serialmessage {
char first[6];
char second[6];
char third[6];
};
serialmessage msg;
memcpy(msg.first, mod1_status_char, 6); // etc.
那么也许最好这样做:
char *char mod1_status_char; // etc.
switch(status) {
case 0x00:
mod1_status_char = strings[0]; // or #define STATUS_OK 0
mod2_status_char = strings[0];
mod3_status_char = strings[0];
break;
case 0x10:
mod1_status_char = strings[0];
mod2_status_char = strings[0];
mod3_status_char = strings[2]; // STATUS_LOW
};
serialmessage msg[3*MAX_STRING_LENGTH+1];
strcpy(msg, mod1_status_char); // or use stpcpy if you have it
strcat(msg, mod2_status_char);
strcat(msg, mod3_status_char);
然后使用strlen(msg)发送结构。 msg在这里并不完全是“动态的”,但它中字符串的长度根据数据而变化,这可能是你想要的。或许我仍然误解了这三个char数组的作用。
在我看来,复制字符串不仅仅是为了引入并发症。通过指针引用它们,直到最后可能的时刻,组装消息,并最小化代码中必须正确获取缓冲区大小的位置数。
答案 1 :(得分:3)
“然后将status_char数组传递给结构,然后使用发送例程发送该结构。”
要非常小心这样做,根据你编码的方式,你可以在那里获得各种垃圾。记住在C中编译器可以填充结构但是它很高兴。
作为旁注,您的字符串缓冲区太短而无法正确保存字符串。使用4个字符+ CR + LF时,您需要一个7个字符的缓冲区,因为您需要存储空终止符'\ 0'。如果你不这样做,不要使用任何'str'函数,因为你没有处理正确的C字符串,所有你要做的就是当有人去读这个/做出改变并发现时,你将要做的更多问题在你的黑客终止之后复制一个str(strcopy正在将“low \ 0”复制到你的缓冲区中,你出于某种原因显然在其他地方抛出/ r / n)使用memcpy。
解决方案:
为什么要复制这些字符串呢?为什么不直接向send函数发送一个指示,告诉它应该发送什么,只是静态分配字符串?
您可以使用(E_LOW,E_OKAY,E_HIGH)的值创建枚举,只需将3个枚举发送到发送函数,并将实际的字符串存储为本地静态变量。如果空间有问题,您可以使用位标志而不是枚举。
你的send函数只需要将字符串值一次一个字节地复制到发送缓冲区并发送strlen()字节。
答案 2 :(得分:1)
我在这里遗漏了什么吗? send例程应该只对字符串使用strlen(),因此它只在缓冲区中发送数据。
serWrite( mod1_status, strlen( mod1_status));
serWrite( "\r\n", 2);
答案 3 :(得分:0)
您可以选择的选项很少:
答案 4 :(得分:0)
截断数组的“head”。
假设您有char words[5]
(或6 - 持有“\ r \ n”)。
因此,如果是“okay”和“high”,则从第一个元素 - words
开始发送words
的内容,如果是低,则从第二个元素开始发送内容:{{ 1}}。
编辑:当然,在这种情况下,您应该从words + 1
开始写“低”,而不是words[1]
。
答案 5 :(得分:0)
我想看看你对MsgStatus_on的定义。
我打赌你有这样的事情:
tyepdef struct {
char descriptor_msg[6];
char address01;
char address02;
char space01;
char cmdmsg01[11];
char statusmsg01[6];
char space02;
char cmdmsg02[5];
char statusmsg02[6];
char space03;
char cmdmsg03[5];
char statusmsg03[6];
char CR;
char LF;
} MsgStatus;
MsgStatus MsgStatus_on;
然后我猜你在调用USARTWrite时会做一个直字节指针,如下所示:
USARTWrite ((char *)&MsgStatus_on, sizeof(MsgStatus_on));
如果是这种情况,那么它会复制缓冲区中的额外字节。实际上它应该在你的所有char数组上添加额外的\ 0。除非你声明所有这些比我做的少,并且当你执行strcpy()时,你实际上是在超越你的数组。它不会导致您出现问题,因为您在下一个语句中设置了超限内存。
另一种选择可能是使用sprintf:
char *message[100] //or some size big enough to hold the whole message.
sprintf (message, "$psu_%d%d op_en op1_%s op2_%s op3_%s\r\n",
address01, address02, mod1_status_char, mod2_status_char, mod3_status_char);
然后致电:
USARTWrite (message, strlen(message));
编辑:哎呀我想这个问题很老了。哦,好吧,我会留下答案,以防它对你有用。