M0学习累计

在实际中遇到过很多问题,如果自己懂得调试程序的话,很多问题可以迎刃而解。将平时调试过程遇到的问题,写下来,加深印象。也加深对于嵌入式程序的调试思路,和方法的理解。

1)遇到Uart接受中断总是进入不了,第一瞬间想到是否打开了接收中断。然后找啊找啊,设置变量啊,也看到了通过串口工具发送数据时后,接收中断已经使能。

2)考虑到是否接线错误。因为连接线是新作的,当时也比较有信心没有问题,一直没有朝这个方向考虑。事实证明,什么问题都有可能发生,多做啊!

 

关于程序延时方法的一些问题

1)两个任务,一个任务负责打开LED,一个任务负责关闭LED。但是同一时间只能有一个任务在操作,采用互斥量的方法来解决这个问题。

每个LED闪烁或关闭的时间有os_dly_wait来确定。但是发现延时的时间严重不准确。

原因:os_dly_wait方法等待一定个 system tick时间,默认的system tick时间是 10000 也就是10ms,同时OS_TIMER 选择 0 Hardware timer。因为之前采用比较老旧的rtx版本 rtx_conf_cm.c 没有OS_TIMER 选择所以,timer运行不正确。这些配置信息,请参考 RTX_Conf_CM.c文件

 

关于mailbox 的使用

在debug的时候,发现mailbox的数据可以通过鼠标放在mailbox变量上面而显示出来。但是显示的数据看不懂是什么意思。做一下实验查看

首先通过串口工具输入 01, 02, 04, 04

mailbox中数据位 01,00,04 , 04 ,每读取一次,最后一个04减少一个。

再次输入 05 ,06 ,07 ,08

mailbox中的数据位 01 ,00 , 08, 04

得出来结论,第三个byte为起始地址,第四个byte为数据长度。

读取mailbox后,不会将数据清0 ,数据仍然会保存在里面,一直到空间写完后,循环替换写入

 

关于uint32_t未定义错误

在新塘的类库中定义了 uint32_t 等数据类型,使用是需要首先引用 nuc1xx.h文件。

但是时常命名已经有引用到该文件,同时在.c文件中已经没有异常出现,但是在实际中会在头文件声明中报错。

原因是在编译的时候,是按照引用顺序编译,如果在编译到某个包含该类型的头文件时,还没有引用nuc1xx.h文件,则会报错,解决办法就是尽量把 nuc1xx.h放在应用该变量的前面。就不会出现问题了

这个问题同样也会存在其他变量里面

另外一种情况:

a.h 中定义了一个 类型,比如说 struct  abc,

b.c 引用了 a.h,那么在b.h 文件中出现 abc的话,是没有问题的

但是如果出现一个c.c文件先引用了b.h ,然后才引用a.h,那么这样的话同样会出现类型未定义

而且会提示是b.h文件中abc类型未定义。这个时候可以查看keil的编译顺序倒数第二个编译文件,检查头文件顺序。

 

关于地址不变,内容不变的变量声明

extern const ResetDataBackup_t* const LgseResetDataBackup   = ( ResetDataBackup_t* )(RESET_DATA_START_ADDR + 0 * ( 5 * BYTE_NUM_IN_ONE_PAGE ) );
extern const ResetDataBackup_t* const ThreeMResetDataBackup = ( ResetDataBackup_t* )(RESET_DATA_START_ADDR + 1 * ( 5 * BYTE_NUM_IN_ONE_PAGE ) );
extern const ResetDataBackup_t* const DealerResetDataBackup = ( ResetDataBackup_t* )(RESET_DATA_START_ADDR + 2 * ( 5 * BYTE_NUM_IN_ONE_PAGE ) );

例如上面代码所定义的变量就是地址不变内容不变的变量。因为这些变量是申明在dataflash里面的,不能通过函数赋值直接写入。只要知道地址,需要使用FMC写入的。

这也算是一个地址不变,值不变的例子

 

关于结构体定义

struct

{

int x;

int y;

} test1;

只是定义了一个结构体变量,下次需要在定义结构体是,需要重写该结构体

 

struct test

{

int x;

int y;

}test1;

定义了结构体 test1,下次在想定义的话 需要用 struct test test2 来定义.

 

typedef struct

{

int x;

int y;

}test;

需要使用 test test1;来定义新的结构体 test1.

 

Cortex M0任务间信号传递-mailbox

任务间的信号传递,可以有很多种——事件,信号量,mailbox

要注意的是在中断状态下,需要使用isr_mbx_xxx函数

 

 

 

 

 

 

串口通讯,之单工通讯

图像 1

三极管导通工作在空闲模式时,TX,RX保持高电平空闲状态。

工作在接受模式时,主机拉低电平,但是此时Tx为高,Ext_TX_LOOPB为低二极管断开,所以只能Rx工作。

工作在发射模式时,Tx为低,将整个电平拉低。但是同时Rx 也拉低也接收到start 信号,在下次接收时需要清空Rx 缓存

 

 

在采用单工Uart时,在发送接收时需要注意信号不要串在一起。

该电路中接收数据的时候,因为二极管的作用,所以发送端无电压的变化。

但是在发送数据的时候,接收端会以前变化。所以在程序处理中需要,发送完成之后丢弃掉Rx buffer中的数据。

**记住不能使用 printf 和scantf因为 printf 和 santf不会触发Uart 中断,所以我们在中断中的处理操作,不会对printf和scanf起到作用。在发射数据的时候,会自己接收到,然后在发送,在接受。。。。

 

RTX OS error

在程序运行时候,突然无征兆的跳到 os_error函数中运行,检查代码没有写错的地方,语法没有不对的(不然也编译不了)问同事运行到os_error一般是队列超出也就是空间不够。检查RTX_CONF_CM.c文件,将堆栈大小改大,问题就解决了。。ps.一般90%问题是这样的,XX 传授的。

 

SPI接口

读取数据一直是0xFF,使用的8位传输。从SPI flash芯片中读取数据一直是0xFF。

原因是SPI芯片初始化不正常

void InitSpi0(void)
{    
    DrvGPIO_InitFunction(E_FUNC_SPI0);
    DrvSPI_Open(eDRVSPI_PORT0, eDRVSPI_MASTER, eDRVSPI_TYPE5, 8);
    DrvSPI_SetEndian(eDRVSPI_PORT0, eDRVSPI_MSB_FIRST);
    DrvSPI_SetTriggerMode(eDRVSPI_PORT0, eDRVSPI_LEVEL_TRIGGER);
    DrvSPI_DisableAutoSS(eDRVSPI_PORT0);
    DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT0, eDRVSPI_ACTIVE_LOW_FALLING); 
    DrvSPI_SetClockFreq(eDRVSPI_PORT0, 4000000, 0);
    DrvSPI_EnableInt(eDRVSPI_PORT0, SPInt_Handler, 0);
}

上例中的代买是正常初始化的代码,可正常使用。

问题2 初始化后读取的数据会间隔。比如说 需要读取  “Hello World” 实际读取出来的确是 “Hl0Wrd”

原因是在使用API方法 DrvSPI_SimpleRead 后,会自动设置CNTRL.GO_Busy为1启动第二次传输。但是我又在后面加了一个设置go_busy位。所以出现改情况。

问题3Flash芯片 擦出不正常,无法正确擦除。

数据Flash芯片 M25P16 擦除之前需要先发送 Write_Enable命令,我整合了WriteEnable 命令和 Erash命令。

但是实际的芯片手册要求Write_Enable命令发送完成之后,需要设置芯片片选为高电平。如果是整合在一起的话,则没有在WriteEnable发送完成之后拉高片选脚。实际上发送不知是什么命令。。提醒自己,一定要仔细的看芯片手册。

问题4发现在读数之后,第一个byte一直是 0,最开始想到的是是否在发送完命令之后,第一次读到的数据无效,需要丢弃。当发现如果设置两个go_busy问题仍然存在,并且整整的第一个字符不见了,问题是接受数组的index错误,一直没有这只 数组的第一个元素,造成一直是0.

如果需要从管脚的角度查看SPI的初始化,可以自己查看SPI API函数。

 

 

Cortex-M0 之新塘 NUC1XX系列寄存器归类总结:

1、系统管理寄存器部分

1)PDID、RSTSRC、IPRSTC1/2BODCR、TEMPCRPORCRGPA/B/C/D/E_MFP、ALT_MFP、REGWRPROT

包括器件ID,系统复位,外设复位,欠压检测,温度传感器,上电复位、多功能管脚控制、复用多功能关键控制、寄存器写保护。

可以看出系统管理部分的寄存器多用在 系统复位控制,外设复位控制,管脚功能选择,和写保护等。

 

 

2、时钟管理控制部分

1)PWRCON、AHBCLK(Advanced High Performance Bus、APBCLK、CLKSTATUS、CLKSEL0、CLKSEL1、CLKSEL2、CLKDIV、PLLCON、FRQDIV

掉电控制,AHB设备时钟(系统总线时钟)、APB设备时钟(外设时钟)、时钟状态、时钟源选择 0/1/2、时钟分频,PLL控制、频率分频器控制

掉电控制: 当芯片掉电时,可以通过中断唤醒芯片。

时钟状态:检测时钟是否处于稳定状态。

 

3、外设寄存器部分

1)通用IO部分

IO模式选择(输入,输出,开漏,准双端),数字使能,管脚数值,去抖动,中断模式(上升沿,下降沿),中断源(检测是否发生中断),去抖动周期

位输出输入控制。

 

以上三部分是一定会使用到的,其他外设部分以后再写。

posted @ 2014-08-07 15:11  侠梦千年  阅读(410)  评论(0编辑  收藏  举报