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

    位输出输入控制。

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

  • 相关阅读:
    Iptables 之二扩展模块 nat
    sudo 命令
    7、CentOS6 编译安装
    MySQL5.7 基础之二 DCL DML
    SQL Server 2008R2安装
    6、httpd2.4 编译安装LAMP
    MySQL 基础之一
    gulp
    msbuild
    inno setup
  • 原文地址:https://www.cnblogs.com/-liszt/p/3897243.html
Copyright © 2020-2023  润新知