【问题标题】:MBed RTOS doesnt respond to serialMBed RTOS 不响应串行
【发布时间】:2017-04-13 19:21:50
【问题描述】:

我正在编写一个应用程序,在该应用程序中我等待来自串行的命令并根据数据转换 LED 颜色。我让每个元素都以自己的方式工作:

  1. 通过串行连接接收和发送命令
  2. 更改 LED 颜色
  3. 收到命令后直接更改 LED 颜色(无 RTOS)。

我需要 LED 循环继续工作,直到新数据到达但是当我使用 RTOS 库中的线程时,LED 不会改变。这让我觉得这是我的代码和 RTOS 的问题,问题是我看不出是什么原因造成的。

从调试(通过串行打印字符串到 pc)我看到线程正在运行并循环,它使用创建变量时设置的值。由于控制台没有输出(或读取串行输入),主线程似乎已停止。

如果我不启动线程,串行通信将再次工作,确认问题出在我的代码和 RTOS 库上。

通过阅读其他论坛和帖子,我了解到这可能是串行和 RTOS 的问题,并遵循删除所有 printf 函数并更改为 RawSerial 的建议,但这没有任何作用。

非常感谢任何帮助以使代码按预期工作

#include "mbed.h"
#include "rtos.h"
#include "xbee.h"
#include "CMDLIB.h"
#include "WS2812.h"
#include "PixelArray.h"

#define LED_COUNT1 134
#define OUT_WHEEL 28

char startChar = '$';
char endChar = ';';

Serial pc( USBTX, USBRX ); // tx, rx

CMDLIB cmd;
xbee xbee( p28, p27, p29, 38400 );
PixelArray px1( LED_COUNT1 );
WS2812 set1( p5, 144, 3, 11, 10, 11 );
Thread ledthread;

int ledFunction;
int colour1[3], colour2[3], speed, intensity;

//LED Functions
void offLED()
{
    for( int i = 1; i < LED_COUNT1; i++ )
    {
        px1.Set( i, 0x000000 );
    }
    set1.write( px1.getBuf() );
}

void solidPulse( int colour, int speed, int intensity )
{
    px1.SetAll( colour );
    //pc.printf("2\r\n");
    set1.write( px1.getBuf() );
    //pc.printf("3\r\n");
    for( int a = 255; a > intensity; a-- )
    {
        px1.SetAllI( a );
        set1.write( px1.getBuf() );
        wait_ms( speed );
        //pc.printf("%d,",a);
    }
    //pc.printf("\r\n4\r\n");
    for( int a = intensity; a < 255; a++ )
    {
        px1.SetAllI( a );
        set1.write( px1.getBuf() );
        wait_ms( speed );
        //pc.printf("%d,",a);
    }
    //pc.printf("\r\n5\r\n");

}

void ledThread()
{
    while( 1 )
    {
        switch( ledFunction )
        {
            case 0: //Off
                //offLED();
            break;
            case 1: //Solid
                //pc.printf("1\r\n");
            solidPulse( cmd.RGB2HEX( colour1[0], colour1[1], colour1[2] ), speed, intensity );
            break;
            case 2: //Solid Pulse
            solidPulse( cmd.RGB2HEX( colour1[0], colour1[1], colour1[2] ), speed, intensity );
            break;
            default:
            break;
        }
        //pc.printf("%d;\r\n", ledFunction);
        wait_ms( 200 );
    }
}

void setup()
{
    set1.useII( WS2812::PER_PIXEL ); // use per-pixel intensity scaling
    xbee.setup( startChar, endChar );
    pc.baud( 38400 );
    muxcon = 0;
    ledFunction = 0;
    for( int j = 0; j < 3; j++ )
    {
        colour1[j] = 1;
        colour2[j] = 1;
    }
    speed = 100;
    intensity = 0;

    for( int i = 0; i < LED_COUNT1; i++ )
    {
        px1.Set( i, 0xffffff );
    }
    set1.write( px1.getBuf() );
}

char * convertChar( string data )
{
    char * chars = "";
    for( int k = 0; k < data.size(); k++ )
    {
        chars += data[k];
    }
    return chars;
}

int main()
{
    setup();
    ledthread.start( ledThread );
    string recData;
    while( true )
    {
        if( xbee.readable() )
        {
            recData = xbee.readData();
            //pc.printf("Recieved Data: %s\r\n",recData);
            string cmdString = cmd.getCommand( recData );
            if( cmdString == "[TEL]" )
            {
                gatherTelemetry();
                string telResult = cmd.formatTelemetry( sData1, sData2, sData3, sData4, sData5, sData6 );
                xbee.sendData( telResult );
            }
            if( cmdString == "[LED]" )
            {
                //pc.printf("[RES],LED;\r\n");

                string res[10];
                int count = 0;
                char c;
                for( int j = 0; j < recData.size(); j++ )
                {
                    c = recData[j];
                    if( c == ',' || c == ';' )
                    {
                        count++;
                    }
                    else
                    {
                        res[count] += c;
                    }
                }
                ledFunction = atoi( res[1].c_str() );
                colour1[0] = atoi( res[2].c_str() );
                colour1[1] = atoi( res[3].c_str() );
                colour1[2] = atoi( res[4].c_str() );
                colour2[0] = atoi( res[5].c_str() );
                colour2[1] = atoi( res[6].c_str() );
                colour2[2] = atoi( res[7].c_str() );
                speed = atoi( res[8].c_str() );
                intensity = atoi( res[9].c_str() );
                //pc.printf("Raw Values: %s-%s-%s-%s-%s-%s-%s-%s-%s-%s\r\n",res[0],res[1],res[2],res[3],res[4],res[5],res[6],res[7],res[8],res[9]);
                //pc.printf("Converted: %d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",ledFunction,colour1[0],colour1[1],colour1[2],colour2[0],colour2[1],colour2[2],speed,intensity);


                xbee.sendData( "[RES],OK" );

                //solidPulse(cmd.RGB2HEX(colour1[0], colour1[1], colour1[2]), speed, intensity);
            }
            if( cmdString == "[CMD]" )
            {

            }
        }
    }
}

【问题讨论】:

    标签: rtos mbed


    【解决方案1】:

    wait_ms 函数不会将正在运行的线程置于等待状态,也不允许其他线程运行。所以你的ledThread 永远不会放弃控制。 相反,ledThread 应该调用Thread::wait,它确实将当前线程置于等待状态并允许下一个就绪线程运行。

    您可能还需要更改 main while 循环,以便它放弃控制并允许 ledThread 再次运行。

    【讨论】:

    • 如何让主线程放弃控制,线程等待?
    • @NoLiver92 :这是一种方式,但在 RTOS 中,可以运行的最高优先级任务将运行。任务在未被阻塞时可以运行。 Thread::wait 是最简单的阻塞方法,但不允许真正实时响应传入的命令;更好的方法是在xbee 上进行阻塞等待;这将要求 xbee 类能够识别 mBed RTOS。那就是你需要阻塞等待来替换xbee::readable()。是否定期轮询 xbee::readable 可能无关紧要,但在需要立即实时响应的其他情况下,轮询可能不够。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    相关资源
    最近更新 更多