微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI蓝牙设计交流 > CC2540串口驱动问题咨询

CC2540串口驱动问题咨询

时间:10-02 整理:3721RD 点击:

下午好啊,各位坛友!

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

      例程中的串口接收是通过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

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

上传头文件

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top