您好我正在研究通过串行总线控制电梯的嵌入式系统。 每次我发送一条消息(数据包包含地址,数据长度,数据,crc)我都需要等待电梯响应,这是由确认包表示的。
每次从电梯收到数据包时都会设置ACK。 接收消息是通过中断完成的。 ACK数据包如下所示:
header('Content-Type: application/json');
当它到来时我将ACK设置为0xA0,0x00,0x00,0x00,0x00
这是我的发送功能:
true
这只是尝试,它不起作用。
bool TransferService::send(char recAddr,char dataLength, char *data){
pc.putc(startByte);
pc.putc(recAddr);
pc.putc(controllerAddress);
pc.putc(dataLength);
for (int i = 0; i < dataLength; i++) {
pc.putc(data[i]);
}
pc.putc(getCrc(recAddr,controllerAddress,data, dataLength));
_messageReceived = false;
timer.reset();
timer.start();
ACK = false;
do {
if (ACK) {
break;
}
} while(timer.read_ms()<=15);
timer.stop();
if (!ACK) {
send(recAddr,dataLength,data);
}
}
我的问题是如何使用protothreads使第一个功能正常工作。
答案 0 :(得分:0)
Protothreads的Adam Dunkels' implementation中的线程函数的结构非常清楚,并且您的函数显然不遵循它。
Protothread线程函数必须返回0.10
,通常具有签名:
int
并且必须使用int threadfunction( struct pt* pt ) ;
宏来定义:
PT_THREAD
来自 Protothread 文档......
protothread函数必须始终返回一个整数,但绝不能返回 显式返回 - 返回在protothread内执行 语句。
查看PT_THREAD( threadfunction( struct pt* pt ) )
{
PT_BEGIN(pt) ;
// thread body here
PT_END(pt) ;
}
的定义我什么都看不到会阻止它与C ++成员函数一起使用,或者使用PT_THREAD
之外的其他参数,在这种情况下,以下是更接近的纠正:
pt
在你的尝试中,你同时拥有一个do-while循环和一个PT_THREAD( TransferService::send( struct pt* pt, char recAddr, char dataLength, char *data )
{
PT_BEGIN( pt );
timer.reset();
timer.start();
pc.putc( startByte );
pc.putc( recAddr );
pc.putc( controllerAddress );
pc.putc( dataLength );
for( int i = 0; i < dataLength; i++ )
{
pc.putc( data[i] );
}
pc.putc( getCrc( recAddr, controllerAddress, data, dataLength ) );
_messageReceived = false;
PT_WAIT_UNTIL( pt, timer.read_ms() > 10 || ACK );
PT_END();
}
,但是WAIT不需要循环。实际上并不需要传递PT_WAIT_UNTIL
参数,所需的pt
可能是类成员甚至是全局(尽管这是不明智的)。
请注意,上述问题遵循了问题中明显的模式,但这将是一种不同寻常的设计模式;大多数情况下,线程无限期地运行而不是单个事务。在不了解整个应用程序的情况下,我建议线程应该在比单个事务struct pt
函数更高的级别运行,这样你就有了一个可以重复执行的“sender”线程发送操作而不退出,如下面的大纲(即不完整或“真实”代码,并有很多假设):
send()
请注意,由于// Constructor...
TransferService::TransferService()
{
PT_INIT( &m_pt ) ; // Where thread state m_pt
// is a member variable of
// type struct pt (or just pt
// since this is C++)
...
}
// Thread function
PT_THREAD(TransferService::senderThread() )
{
PT_BEGIN(&m_pt);
for(;;)
{
PT_WAIT_UNTIL( &m_pt, ready_to_send ) ;
timer.reset();
timer.start();
send( recAddr, dataLength, data ) ;
PT_WAIT_UNTIL( &m_pt, timer.read_ms() > 10 || ACK );
}
PT_END(pt);
}
// Single send transaction function
bool TransferService::send( char recAddr, char dataLength, char *data )
{
pc.putc( startByte );
pc.putc( recAddr );
pc.putc( controllerAddress );
pc.putc( dataLength );
for( int i = 0; i < dataLength; i++ )
{
pc.putc( data[i] );
}
pc.putc( getCrc( recAddr, controllerAddress, data, dataLength ) );
_messageReceived = false;
}
API的工作方式,PT_...
必须与PT_WAIT_UNTIL
和PT_BEGIN
功能相同,因此移动计时器在上面的代码中等待。