使用 tiva 系列 c 将数据从微控制器发送到计算机
sending data from microcontroller to the computer using tiva series c
我将 Tiva C 系列 TM4C123GH6PM 与 Code Composer Studio 结合使用,以从另一个相同类型的微控制器获取数据。好吧,我以字节为单位获取数据。项目的目标是 assemble 每 8 个字节并将它们转换为双精度然后将这些双精度发送到计算机。我必须使用USART将数据发送到计算机。
当我使用USART时,我有两种方法:
- 一个从USART_x获取数据:UARTCharGet(UART1_BASE)
- 另一个通过 USART_x 发送数据:UARTCharPut(UART0_BASE,d)
问题在于有两种只接受字符的方法。因此,将这些方法用于 double 是不可能的,因为 double 是 8 个字节,而一个字符是一个字节。我正在尝试将双打发送到我的计算机。有什么想法吗?
第二个问题是在计算机端写一个程序,从微控制器中获取数据(字节)。
我应该用 c 语言编写这个程序吗(另一种方法是使用 matlab,因为我将使用这些数据进行模拟)?
如何在 c(或者如果可能的话在 matlab 中)访问 com-Port?
一般来说,您遇到的是序列化问题,最好的方法是为此目的使用专门的库。
你可以用一种肮脏但简单的方法来解决它。 你得好好assemble你另一边的数据恢复到原来的两倍。
typedef union _MyDouble {
double d;
unsigned char bytes[sizeof(double)];
} MyDouble;
MyDouble my_double;
my_double.d = 1.234;
for(i=0; i < sizeof(double); i++) {
UARTCharPut(UART0_BASE, (char)my_double.bytes[i]).
}
另一件事是,如果您使用 UART,则应将此联合封装到某个框架中,例如为了在另一边成功地重新assemble这个。
_____________ ________ __________ ___________ ________
| | | | | |
| FRAME_BEGIN | LENGTH | MyDouble | FRAME_END | CRC-8? |
|_____________|________|__________|___________|________|
接下来您可能应该对该结构强制执行字节对齐,这是由编译器指令完成的。它确保您的结构没有填充字节等,并分配最小需要的大小。这在嵌入式应用程序用例中非常流行,在这些用例中,一些二进制对象将在串行接口上传输——这正是您的情况。这种简单的解决方案可能适用于特定的硬件+软件配置,但从专业的角度来看,它肯定不是可移植的好解决方案。
你需要找到一种方法来分解大量数据,并将其发送给客户端,然后客户端需要一种方法来重新assemble数据,并且还需要知道这些数据何时被处理已发送。
一个非常简单的方法是将双精度数的所有数字转换为字符。效率低下,但它很容易完成工作,如下所示。这是可取的原因是因为它可以让您轻松创建自己的 "instruction set"。例如,您可以将字符 '!'
保留为 "the letter following !
denotes a special instruction",这样当客户端看到序列“!d
”时,它就知道接下来的 32 个字节的数据代表一个 double
,并重新assemble它。
如果您只发送原始字节,当您想要创建转义码或操作码以向客户端发出特殊情况信号时,它会变得更加复杂。
代码清单
#include <stdio.h>
#define BUF_LEN (32)
typedef union {
float f;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} double_cast;
int main(void)
{
double_cast d1;
d1.f = 0.15625;
printf("sign = %x\n",d1.parts.sign);
printf("exponent = %x\n",d1.parts.exponent);
printf("mantissa = %x\n",d1.parts.mantissa);
char buf[BUF_LEN+1] = { 0 };
snprintf(buf, BUF_LEN+1, "%01X%08X%023X", d1.parts.sign, d1.parts.exponent,
d1.parts.mantissa);
// Send over UART
printf("Double as string: [%s]\n", buf);
//UART_printf("!d%s", buf);
return 0;
}
示例输出
sign = 0
exponent = 7c
mantissa = 200000
Double as string: [00000007C0000000000000000020000]
Credit for the code to break a double into a string goes to u/eran.
另一个适合我的解决方案(类似于 Krystian 的解决方案)。我定义了一个函数,它的参数是一个双精度数和一个字节数组。 double 必须转换为字节数组。这就是为什么我定义了一个大小为 8 字节的字节数组。这里有一些代码:
unsigned char bytesArray[sizeof(double)];
unsigned char * doubleToBytes(double num,unsigned char bytes []){
return memcpy(bytes,&num,sizeof(double));
}
获取数组中的字节后,您可以使用以下循环发送数据:
for(i=0;i<sizeof(double);i++){
UARTCharPut(UART1_BASE,(unsigned char)*(bytesArray+i));
}
我将 Tiva C 系列 TM4C123GH6PM 与 Code Composer Studio 结合使用,以从另一个相同类型的微控制器获取数据。好吧,我以字节为单位获取数据。项目的目标是 assemble 每 8 个字节并将它们转换为双精度然后将这些双精度发送到计算机。我必须使用USART将数据发送到计算机。
当我使用USART时,我有两种方法:
- 一个从USART_x获取数据:UARTCharGet(UART1_BASE)
- 另一个通过 USART_x 发送数据:UARTCharPut(UART0_BASE,d)
问题在于有两种只接受字符的方法。因此,将这些方法用于 double 是不可能的,因为 double 是 8 个字节,而一个字符是一个字节。我正在尝试将双打发送到我的计算机。有什么想法吗?
第二个问题是在计算机端写一个程序,从微控制器中获取数据(字节)。
我应该用 c 语言编写这个程序吗(另一种方法是使用 matlab,因为我将使用这些数据进行模拟)? 如何在 c(或者如果可能的话在 matlab 中)访问 com-Port?
一般来说,您遇到的是序列化问题,最好的方法是为此目的使用专门的库。
你可以用一种肮脏但简单的方法来解决它。 你得好好assemble你另一边的数据恢复到原来的两倍。
typedef union _MyDouble {
double d;
unsigned char bytes[sizeof(double)];
} MyDouble;
MyDouble my_double;
my_double.d = 1.234;
for(i=0; i < sizeof(double); i++) {
UARTCharPut(UART0_BASE, (char)my_double.bytes[i]).
}
另一件事是,如果您使用 UART,则应将此联合封装到某个框架中,例如为了在另一边成功地重新assemble这个。
_____________ ________ __________ ___________ ________
| | | | | |
| FRAME_BEGIN | LENGTH | MyDouble | FRAME_END | CRC-8? |
|_____________|________|__________|___________|________|
接下来您可能应该对该结构强制执行字节对齐,这是由编译器指令完成的。它确保您的结构没有填充字节等,并分配最小需要的大小。这在嵌入式应用程序用例中非常流行,在这些用例中,一些二进制对象将在串行接口上传输——这正是您的情况。这种简单的解决方案可能适用于特定的硬件+软件配置,但从专业的角度来看,它肯定不是可移植的好解决方案。
你需要找到一种方法来分解大量数据,并将其发送给客户端,然后客户端需要一种方法来重新assemble数据,并且还需要知道这些数据何时被处理已发送。
一个非常简单的方法是将双精度数的所有数字转换为字符。效率低下,但它很容易完成工作,如下所示。这是可取的原因是因为它可以让您轻松创建自己的 "instruction set"。例如,您可以将字符 '!'
保留为 "the letter following !
denotes a special instruction",这样当客户端看到序列“!d
”时,它就知道接下来的 32 个字节的数据代表一个 double
,并重新assemble它。
如果您只发送原始字节,当您想要创建转义码或操作码以向客户端发出特殊情况信号时,它会变得更加复杂。
代码清单
#include <stdio.h>
#define BUF_LEN (32)
typedef union {
float f;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} double_cast;
int main(void)
{
double_cast d1;
d1.f = 0.15625;
printf("sign = %x\n",d1.parts.sign);
printf("exponent = %x\n",d1.parts.exponent);
printf("mantissa = %x\n",d1.parts.mantissa);
char buf[BUF_LEN+1] = { 0 };
snprintf(buf, BUF_LEN+1, "%01X%08X%023X", d1.parts.sign, d1.parts.exponent,
d1.parts.mantissa);
// Send over UART
printf("Double as string: [%s]\n", buf);
//UART_printf("!d%s", buf);
return 0;
}
示例输出
sign = 0
exponent = 7c
mantissa = 200000
Double as string: [00000007C0000000000000000020000]
Credit for the code to break a double into a string goes to u/eran.
另一个适合我的解决方案(类似于 Krystian 的解决方案)。我定义了一个函数,它的参数是一个双精度数和一个字节数组。 double 必须转换为字节数组。这就是为什么我定义了一个大小为 8 字节的字节数组。这里有一些代码:
unsigned char bytesArray[sizeof(double)];
unsigned char * doubleToBytes(double num,unsigned char bytes []){
return memcpy(bytes,&num,sizeof(double));
}
获取数组中的字节后,您可以使用以下循环发送数据:
for(i=0;i<sizeof(double);i++){
UARTCharPut(UART1_BASE,(unsigned char)*(bytesArray+i));
}