This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2540串口驱动问题咨询

Other Parts Discussed in Thread: CC2540

下午好啊,各位坛友!

      官方提供的例程中有串口的驱动、读、写等函数,用起来挺方便的。但是这部分驱动看起来一点也不比协议栈简单啊。。。改起来也有些难度!有没有专门这方面的资料说明呢?

      例程中的串口接收是通过DMA轮询,并将事件反馈到用户注册的回调函数中。串口的接收必须有时钟信号的支持,这样CPU就无法睡眠了。

      NPI_InitTransport(NPI_SerialCallback);//注册串口事件回调函数

      我有个想法,不知是否行得通:在外部(MCU与CC2540串口通信)发送串口数据前拉低CC2540一个引脚的电平,通过外部中断来唤醒CC2540,而CC2540中断后则保持CPU不睡眠,直到数据接收完毕再进行睡眠。例程中的串口接收能否支持这样的工作方式呢?

  • shaokai,

    DMA 必须要有时钟信号。

    可以,你可以用一个GPIO 唤醒系统再去搬运UART 数据。但注意,最好是先让外部MCU 通过GPIO 唤醒2540, 然后MCU再向UART 口发送数据,以免前几个字节数据丢失。

  • Yan,

        我快被驱动搞疯了,我在预处理器定义使用了串口驱动HAL_UART=TRUE和节能模式POWER_SAVING。

    这下好,编译警告地址为0X6B的中断向量重复定义。打开_hal_uart_dma.c一看,莫名其妙的多了个P0口的中断处理函数,而我在按键模块已定义过P0口的中断处理函数。

        看了下预编译,只有在#if (HAL_UART_DMA == 1),且定义了POWER_SAVING 才会增加P0中断处理函数的编译。

        HAL_ISR_FUNCTION(port0Isr, P0INT_VECTOR)

        我不太明白,为何要在这里增加这个中断处理函数?可以去掉吗?调的真想哭啊。。。

  • shaokai,

    HAL_UART_DMA == 1 的时候, UART 会用DMA 模式搬运数据。你这个应该不是因为 POWER_SAVING,是因为DMA。

    这个中断处理不能去除。

    你看一下是否其他地方有重定义了0X6B 向量的中断处理,比如按键或者其他IO 之类,然后换个其他中断向量就行。

  • Yan,

          DMA搬运数据为什么跟P0口的外部中断有关系呢?这点不是很明白。

          另外,在simpleBLEPeripheral这个工程中似乎并未加入_hal_uart_dma.c这个文件(工程栏目中找不到),只是在Option->C/C++ Complier->Preprocessor中有这个链接关系:$PROJ_DIR$\..\..\..\..\Components\hal\target\CC2540EB。

          我是在自己写的中断处理函数处,右击P0INT_VECTOR后通过Find All References of 'P0INT_VECTOR' 跳转到这个文件的。

          既然_hal_uart_dma.c未加入工程,我想应该不会影响编译吧(编译器应该只是编译已加入工程的文件)?——但是会警告,不解~~~

  • Yan

          串口初始化时,需要注册用户处理串口事件的回调函数。

    NPI_InitTransport(NPI_UART_CB);

    我在回调函数中,检测收到的事件。在屏蔽POWER_SAVING的情况下,发送完数据可以收到HAL_UART_TX_EMPTY的事件,但是一旦使能POWER_SAVING则收不到这个事件。这是为什么呢?难道DMA中数据还未发送完又进入睡眠状态了?

    void NPI_UART_CB(uint8 port,uint8 event)
    {
    if(event & HAL_UART_TX_EMPTY)//发送空
    {
    FrameTxState = Finish;
    HalLedSet(HAL_LED_2,HAL_LED_MODE_TOGGLE);
    }
    if(event & HAL_UART_RX_TIMEOUT)//有数据等待接收
    {
    }
    }

    为此我还修改了部分代码:

    uint16 NPI_WriteTransport( uint8 *buf, uint16 len )
    {
    FrameTxState = Doing;
    return( HalUARTWrite( NPI_UART_PORT, buf, len ) );
    }

    OSAL.C中修改了void osal_run_system( void )

    {

    #if defined( POWER_SAVING )
    else // Complete pass through all task events with no activity?
    {
    if(FrameTxState == Finish)
    {
    HalLedSet(HAL_LED_1,HAL_LED_MODE_ON);
    osal_pwrmgr_powerconserve(); // Put the processor/system into sleep
    }
    }
    #endif

    }

    其他地方没有改变,数据就是发不出去,还是失败了。

    我想知道,如何使DMA数据发送完了才进入睡眠?

  • shaokai,

    首先,DMA 是需要clock 才能工作的。如果有POWER_SAVING,那么就会有可能把外部晶振关闭,那么DMA就不工作了。

    P0 中断是UART 中断,因为你用的是P0 口来配置UART。UART 挂在在P0上。

    请不要修改osal_run_system()里面的东西,特别涉及到power management的代码,因为这是系统自动来控制的。

    你可以尝试 用 osal_pwrmgr_device(  );  参数有 PWRMGR_BATTERY 和 PWRMGR_ALWAYS_ON, 用这个来尝试一下模式变换。

  • Yan,

          还是有问题啊:在初始化时,打印就没问题

    NPI_InitTransport(NPI_UART_CB);
    NPI_WriteTransport("Hello\n\0",7);

          但是后面的按键响应打印还是无数据

    if ( keys & HAL_KEY_SW_1 )
    {
    SK_Keys |= SK_KEY_LEFT;
    NPI_WriteTransport("Key1 SP\n",8);
    }

    if ( keys & HAL_KEY_SW_2 )
    {
    NPI_WriteTransport("Key2 SP\n",8);
    SK_Keys |= SK_KEY_RIGHT;

    ...

    }

    把POWER_SAVING屏蔽了,就OK。给我的感觉就是一旦睡眠过,DMA就无法再收发数据了。

    我试过用PWRMGR_ALWAYS_ON也不行。

  • shaokai,

    理论上,你只要在打印之前,唤醒32M 晶振,然后用PWRMGR_ALWAYS_ON,那应该是没有问题的。

    建议你debug 打印的时候,还是把POWER_SAVING 关闭,然后关闭debug的时候,以正常的POWER_SAVING模式运行。

  • Yan

          我不是在debug时候跟踪打印的,我把程序改好了,烧到2540里跑的。

          我试过POWER_SAVING,并在打印之前,使用PWRMGR_ALWAYS_ON。还是无效啊。只能屏蔽POWER_SAVING.

  • hi, shaokai Lin

    我碰到的问题跟你是一样的,就算一开始就打开PWRMGR_ALWAYS_ON也不行,只能发个两三秒钟,后面就再也发不了了。你现在解决了这个问题没?

  • 嗯啊~

    太久没弄,有些都忘了,不过你要注意以下几点:

    1. 启动后开启一个周期任务,osal_start_timerEx(UserTask_ID,USER_PERIOD,1000);//保证CPU不会进入到PM3模式,周期可以设大一点

    2.还有就是修改下DMA的一个宏定义,把  #define DMA_PM     1         改为  #define DMA_PM       0

  • 您好,

    我之前的UART驱动,之前有分享一篇帖子

    http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/61462.aspx

    里面的串口透传程序就是使用的这个驱动,请参考。