在 8 位 UART 上发送 16 位值
Sending 16 bit values on 8 bit UART
我们正在尝试将 16 位值从一个 PSoC 发送到另一个。
这个操作的本质应该很简单:
- 将值拆分为两个 8 位值,一个用于 MSB,一个用于 LSB
- 从系统 1 发送 MSB,然后发送 LSB
- 在系统 2 上接收 MSB,然后接收 LSB
- 通过移位 MSB 然后对 LSB 进行 OR 掩码来合并两个字节。
- 利润
所以我们在实践中这样做的方式是:
//Split and send
uint16 utest = (uint16)test;
uint8 hibyte = utest>>8;
uint8 lowbyte = utest;
UART_PutChar(hibyte);
UART_PutChar(lowbyte);
系统 2(收到字节的 ISR):
//Recieve and merge
uint8 rx_msb = UART_GetByte();
uint8 rx_lsb = UART_GetByte();
rx_udata = ((uint16)rx_msb << 8) | rx_lsb;
sprintf(TransmitBufferUSB,"%d\n\r",rx_udata);
UART_USB_PutString(TransmitBufferUSB);
问题在于此代码不一致。而且我们几乎从来没有接收到与我们发送的相同的数据。
当我们尝试通过系统 2 中的 UART_USB_PutString 函数将数据发送到计算机时出现另一个问题。我们在 putty 终端中收到两组 %d\n\r,其中一组可能是发送的正确值,而另一个似乎是随机的。
其他信息
- PSoC:CY8CKIT-059
- IDE:赛普拉斯 PSoC Creator 4.1
- 终端:Putty
- 发件人代码:https://pastebin.com/4SfYGuSw
- 收件人代码:https://pastebin.com/90c7p2zJ
请记住,这是我们第一次在任何设置中使用 UART,因此如果您有任何提示和技巧,我们也可以使用。
如果您需要任何其他信息或对如何解决这个破烂问题有任何想法,请告诉我们。
真诚的两位从事 PSoC 工作的新手电子学生
\de_rush
首先,即使您禁用了中断,在中断例程中使用 sprintf 也是一个非常糟糕的主意。更糟糕的是将数据发送到那里 :)
你可能是一个非常非常初学者。始终保持中断例程尽可能短。
将调试代码移到中断之外。
其次你只能读取你在中断中收到的内容(这是一个字节)并且你读取了两个。
最后我不认为 UART_GetByte
是发明来用于中断例程的。只需读取数据寄存器即可。
我个人更喜欢工会。
typedef union
{
uint16_t u16;
int16_t i16;
uint8_t b[2];
}data16;
volatile data16 revcb, tb; // tb can be local and not volatile
volatile int pointer = 0;
volatile int flag = 0;
CY_ISR(UART_ISR){
Status_pin_Write(0xFF); //Used for debugging
revcb.b[pointer] = dataregister; // place the appripriate code here
pointer = ! pointer;
if(!pointer) flag = 1;
Status_pin_Write(0x00);
}
//in the main function
while(1)
{
if(flag)
{
ISR_Rx_Disable(); // make it atomic
tb = recv;
flag = 0;
ISR_Rx_Enable();
sprintf(TransmitBufferUSB,"%d\n\r",tb.u16);
UART_USB_PutString(TransmitBufferUSB);
}
}
但请记住 - 当您发送调试数据时 - 可能会出现许多其他值,您可能会丢失一些东西。您需要实现一个循环缓冲区 - 但这超出了这个问题的范围。
我们正在尝试将 16 位值从一个 PSoC 发送到另一个。 这个操作的本质应该很简单:
- 将值拆分为两个 8 位值,一个用于 MSB,一个用于 LSB
- 从系统 1 发送 MSB,然后发送 LSB
- 在系统 2 上接收 MSB,然后接收 LSB
- 通过移位 MSB 然后对 LSB 进行 OR 掩码来合并两个字节。
- 利润
所以我们在实践中这样做的方式是:
//Split and send
uint16 utest = (uint16)test;
uint8 hibyte = utest>>8;
uint8 lowbyte = utest;
UART_PutChar(hibyte);
UART_PutChar(lowbyte);
系统 2(收到字节的 ISR):
//Recieve and merge
uint8 rx_msb = UART_GetByte();
uint8 rx_lsb = UART_GetByte();
rx_udata = ((uint16)rx_msb << 8) | rx_lsb;
sprintf(TransmitBufferUSB,"%d\n\r",rx_udata);
UART_USB_PutString(TransmitBufferUSB);
问题在于此代码不一致。而且我们几乎从来没有接收到与我们发送的相同的数据。
当我们尝试通过系统 2 中的 UART_USB_PutString 函数将数据发送到计算机时出现另一个问题。我们在 putty 终端中收到两组 %d\n\r,其中一组可能是发送的正确值,而另一个似乎是随机的。
其他信息
- PSoC:CY8CKIT-059
- IDE:赛普拉斯 PSoC Creator 4.1
- 终端:Putty
- 发件人代码:https://pastebin.com/4SfYGuSw
- 收件人代码:https://pastebin.com/90c7p2zJ
请记住,这是我们第一次在任何设置中使用 UART,因此如果您有任何提示和技巧,我们也可以使用。 如果您需要任何其他信息或对如何解决这个破烂问题有任何想法,请告诉我们。
真诚的两位从事 PSoC 工作的新手电子学生
\de_rush
首先,即使您禁用了中断,在中断例程中使用 sprintf 也是一个非常糟糕的主意。更糟糕的是将数据发送到那里 :) 你可能是一个非常非常初学者。始终保持中断例程尽可能短。
将调试代码移到中断之外。
其次你只能读取你在中断中收到的内容(这是一个字节)并且你读取了两个。
最后我不认为 UART_GetByte
是发明来用于中断例程的。只需读取数据寄存器即可。
我个人更喜欢工会。
typedef union
{
uint16_t u16;
int16_t i16;
uint8_t b[2];
}data16;
volatile data16 revcb, tb; // tb can be local and not volatile
volatile int pointer = 0;
volatile int flag = 0;
CY_ISR(UART_ISR){
Status_pin_Write(0xFF); //Used for debugging
revcb.b[pointer] = dataregister; // place the appripriate code here
pointer = ! pointer;
if(!pointer) flag = 1;
Status_pin_Write(0x00);
}
//in the main function
while(1)
{
if(flag)
{
ISR_Rx_Disable(); // make it atomic
tb = recv;
flag = 0;
ISR_Rx_Enable();
sprintf(TransmitBufferUSB,"%d\n\r",tb.u16);
UART_USB_PutString(TransmitBufferUSB);
}
}
但请记住 - 当您发送调试数据时 - 可能会出现许多其他值,您可能会丢失一些东西。您需要实现一个循环缓冲区 - 但这超出了这个问题的范围。