N76E003开发笔记(关于使用N76E003过程遇到的问题)

发布者:AngelicHeart最新更新时间:2022-07-07 来源: csdn关键字:N76E003  开发笔记  接收中断 手机看文章 扫描二维码
随时随地手机看文章

1.N76E003使用双串口串口1无法进入接收中断

N76E003在使能串口中断后,发送串口数据时,必须要先读TI/TI_1寄存器,再进入发送中断,并在中断中清除TI/TI_1寄存器的值。如若不然,则在串口0发送数据后将导致串口1无法进入中断。并且,经过测试发现,在这种情况下代码执行速度慢于正常情况下的速度。可以用一个简单的delay函数测试


一个完整的串口发送流程为:TI/TI_1清零--> SBUF/SBUF_1赋值-->轮询TI/TI_1的值(在发送成功后,会先被当前程序轮询到其值为1,再进入中断程序)-->进入中断-->清楚TI/TI_1


示例代码:


以使用N76E003官方bsp库为例。


void Send_Data_To_UART0(uint8_t c)


{


    TI = 0;    


    SBUF = c;


    while(TI==0);


}


void SerialPort0_ISR(void) interrupt 4


{


    if (RI==1)


    {                  /* if reception occur */


       clr_RI;       /* clear reception flag for next reception */


    }


   


    if(TI==1)


    {


       clr_TI;        /* if emission occur */


    }


}


void Send_Data_To_UART1(uint8_t c)


{


    TI_1 = 0;


    SBUF_1 = c;


    while(TI_1==0);


}


void SerialPort1_ISR(void) interrupt 15


{


    if (RI_1==1)


    {                          /* if reception occur */


       clr_RI_1;           /* clear reception flag for next reception */


    }


   


    if(TI_1==1)


    {


       clr_TI_1;           /* if emission occur */


    }


}


2.使用双串口,波特率异常(115200 bps)

如下图通过数据手册可以看出在16Mhz的时钟下115200会有较大误差,故须将时钟配置为16.6Mhz

使用双串口的情况下串口0使用timer1作为时钟,串口1使用timer3作为时钟,在这种情况下,实际上timer1的时钟是16.588Mhz,需要按16.588Mhz来计算波特率,否则波特率有较大误差。(即便如此,在某些芯片上,波特率仍有固定误差,应和物料有关)

系统时钟16.6Mhz设置代码如下:


void MODIFY_HIRC_16588(void)


{   


    unsigned char hircmap0,hircmap1;


    unsigned int    trimvalue16bit;


    set_IAPEN;   


    IAPAL = 0x30;      


    IAPAH = 0x00;      


    IAPCN = READ_UID;   


    set_IAPGO;   


    hircmap0 = IAPFD;   


    IAPAL = 0x31;      


    IAPAH = 0x00;   


    set_IAPGO;   


    hircmap1 = IAPFD;  


    clr_IAPEN;       


    //hircmap1 = hircmap1&0x01;   


    trimvalue16bit = ((hircmap0<<1)+(hircmap1&0x01));  


    trimvalue16bit = trimvalue16bit - 15;  


    hircmap1 = trimvalue16bit&0x01;  


    hircmap0 = trimvalue16bit>>1;   

    BIT_TMP=EA;


    EA=0;


    TA=0XAA;   


    TA=0X55;  


    RCTRIM0 = hircmap0;  


    TA=0XAA;   


    TA=0X55;  


    RCTRIM1 = hircmap1;


    EA=BIT_TMP;


}


波特率设置示例代码如下:


void InitialUART0_Timer1(UINT32 u32Baudrate)    //T1M = 1, SMOD = 1


{


    SCON = 0x52;     //UART0 Mode1,REN=1,TI=1


    TMOD |= 0x20;    //Timer1 Mode1


    set_SMOD;        //UART0 Double Rate Enable


    set_T1M;


    clr_BRCK;        //Serial port 0 baud rate clock source = Timer1


 


#ifdef FOSC_160000


    //TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */


    TH1 = 256 - (1036750/u32Baudrate+1);         /*16.588 MHz */


       //TH1 = 256 - (1037500/u32Baudrate+1);         /*16.6 MHz */


#endif       


#ifdef FOSC_221184


    TH1 = 256 - (1382400/u32Baudrate);                /*22.1184 MHz */


#endif


    set_TR1;


}


void InitialUART1_Timer3(UINT32 u32Baudrate) //use timer3 as Baudrate generator


{


              P02_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit


              P16_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit


      


             SCON_1 = 0x50;        //UART1 Mode1,REN_1=1,TI_1=1


           T3CON = 0x08;          //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1), UART1 in MODE 1


              clr_BRCK;


#ifdef FOSC_160000


              //RH3    = HIBYTE(65536 - (1000000/u32Baudrate)-1);            /*16 MHz */


              //RL3    = LOBYTE(65536 - (1000000/u32Baudrate)-1);                     /*16 MHz */


 


              RH3    = HIBYTE(65536 - (1037500/u32Baudrate));           /*16.6 MHz */


           RL3    = LOBYTE(65536 - (1037500/u32Baudrate));                    /*16.6 MHz */


#endif


#ifdef FOSC_166000


              RH3    = HIBYTE(65536 - (1037500/u32Baudrate));                  /*16.6 MHz */


              RL3    = LOBYTE(65536 - (1037500/u32Baudrate));                           /*16.6 MHz */


#endif


    set_TR3;         //Trigger Timer3


}


3.管脚中断触发方式在中断中无法切换

在使用过程中发现如果先使能一个管脚中断为上升沿触发,再在中断中设置为下降沿触发,将会设置失败,下降沿将无法触发。必须退出中断后设置。


4.mcu软件启动方式切换后某些定时器未停止

在使用中发现如果软件从aprom重启并跳转到ldrom,若之前使能了定时器,则在ldrom代码中必须先停止定时器再清除TH0、TL0寄存器,然后再开始定时器(如果需要使用)。否则定时将异常(由于只使用timer 0作为通用定时器,故其他定时未验证)。


初始化定时器前清空TR0,数据手册有如下说明:在模式0或模式1下时,当读/写TH0(TH1)和TL0(TL1)之前,必须清除TR0(TR1)来停止计时。否则将产生不可预料的结果。


示例代码:


void Enter_IAP(void)


{


    DEBUG("enter iaprn");


    default_config[0] &= ~0x80;


    program_config(BYTE_PROGRAM_CONFIG, default_config, 4);


//    Delay10us(20);


    BIT_TMP=EA;


    EA=0;


   


    TA = 0xAA;


    TA = 0x55;


    CHPCON |= SET_BIT1;     // set boot from LP


    TA = 0xAA;


    TA = 0x55;


    CHPCON |= 0x80;     //  software reset enable


   


    EA=BIT_TMP;


}


void TM0_Init(void)


{            


    clr_TR0;                 //stop timer0 (if want reset TH0 or TL0,must clr TR0)


       TH0=TL0=0;          //interrupt timer 5.92 ms


       set_TR0;                //Start timer0


       IE = 0x92;             //EA=1, ES=1,ET0=1


}


5.掉电模式N76E003功耗偏高

可以有效降低掉电模式功耗的措施:


clr_BODEN; //关闭BOD欠压检测(通过代码关闭未验证,但在下载程序时取消该选项功耗降低明显)


clr_HIRCEN ;//关闭高速HIRC时钟(未使用)


clr_CLOEN; //关闭系统时钟输出(未验证)


clr_ADCEN;//关闭adc模块(已验证,有效防止漏电)


正常情况下,N76E003通过设置PCON寄存器的PD位进入待机模式时,mcu功耗只有5~6ua(只关闭欠压检测BOD,其他不动),但经过测试发现,如果进入掉电模式前使能了adc功能,则会导致该I/O管脚漏电,导致功耗达到几百ua,正确做法是在进入掉电模式前关闭adc模块。


示例代码:(以P04为例)


#define CLR_ADC     P04_Input_Mode;clr_ADCEN;clr_ADCS


6.掉电模式N76E003的I/O引脚驱动能力不足

经过测试发现,在进入掉电模式后,N76E003的I/O输出电流将大幅降低,在部分应用场景下需要先将I/O引脚设置为推完模式,在进入掉电模式才能驱动部分电路。(包括但不限于某些wifi芯片的使能脚等)。相关文档如下图:

7.看门狗超时复位的最大超时时间过短

有别于其他mcu,N76E003的看门狗最大超时时间只有1.638s。其看门狗使用方式为:看门狗中断产生-->进入中断-->中断中喂狗。只要在看门狗中断触发的512个LIRC时钟周期内喂狗即可。相关文档如下图:

8. ADC采集电压第一次不准

在使用中发现N76E003的adc引脚如果之前的模式配置为准双向模式(其他模式未测试),则若是将改引脚设置为输入模式马上读取adc电压值,则会导致adc读取电压不准的情况(此时连续读取三次均不准),必需要等待一段时间,经测试几十个指令周期后即可。(时间可根据应用场景验证)。该现象的原因可能是外部电路给adc引脚的驱动电流较小,使adc引脚状态转换较慢。


9.mcu区分外部复位和上电复位

N76E003的AUXR1.6寄存器RSTPINF为复位标志位,但是上电复位和外部复位都将使该标志位置位,若只使用这个复位引脚将无法区分这两种复位状态。但可通过PCON的POF(上电复位标志位)标志位来加以判断。该位只在上电复位时置位。即引脚复位的情况为:POF为0,RSTPINF为1.


10. 关于N76E003的Keil编译器优化级别

经过测试发现如下问题:


串口代码,如果优化级别不是8,则存在串口无法正常使用的情况,即使变量定义为volatile类型亦然,且其官方bsp示例代码的工程配置优化级别均为8,若修改其优化级别,同样存在这个问题。

存在函数只声明但不定义但能编

译通过的情况。

存在头文件缺少#endif但能编译通过的情况

存在变量只extern声明未定义但能编译通过的情况


综上,编译器的警告信息一定要去关注!!!


关键字:N76E003  开发笔记  接收中断 引用地址:N76E003开发笔记(关于使用N76E003过程遇到的问题)

上一篇:MS51替换N76E003注意事项
下一篇:N76E003配置看门狗watchdog

推荐阅读最新更新时间:2024-11-12 18:39

STM32串口中断接收方式详细比较
简介:本例程通过PC机的串口调试助手将数据发送至STM32,接收数据后将所接收的数据又发送至PC机,具体下面详谈 实例一: void USART1_IRQHandler(u8 GetData) { u8 BackData; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //中断产生 { USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志. GetData = UART1_GetByte(BackData); //也行GetData=USART1- DR; USART1_SendByte(GetData);
[单片机]
STM32开发笔记76: 初始化RTC后死机的原因
项目开发中只要初始化RTC,则系统死机。其初始化步骤可参考日志:STM32开发笔记44:RTC驱动程序的移植。按照日志STM32开发笔记75: 使用STM32CubeMX点亮一个LED使用STM32CubeMX直接生成程序则运行正常。 分析原因在于,少移植了2个函数:HAL_RTC_MspInit和HAL_RTC_MspDeInit。这两个函数的实现非常简单,可以靠STM32CubeMX直接生成。 void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) { __HAL_RCC_RTC_ENABLE(); HAL_NVIC_SetPriority(RTC_IRQn, 0x0, 0)
[单片机]
51单片机中用中断方式实现串口数据发送与接收
/* Description:用中断方式实现串口数据发送 Author:Jcy Date:2012-5-2 */ #include reg52.h #define uint unsigned int #define uchar unsigned char uchar receive_ser; //串口接收到的数据 uchar flag=0; uchar receivebuf = Jcy ; uchar i=0; uchar j; void init_ser() { TMOD=0X20;//定时器1工作在方式2 TH1=0XFD; TL1=0XFD; //波特率9600,51单片机大多用这个 TR
[单片机]
STM32单片机串口空闲中断接收不定长数据
在使用单片机的串口通信功能时,常用的接收数据方法是通过固定的字节数来判断一帧数是否发送完成,或者是通过固定的结束标志位来表示一帧数据发送完成。但是有时候会遇到发送的数据长度不固定,也没有固定的结束标志,对于这样的数据通常的做法是每隔一段时间查看一下接收数据的长度是否发生了变化,如果指定的一段时间内接收数据长度没有发生变化,就认为是一帧数据发送完成。在STM32单片机中串口提供了一个更好用的功能,就是空闲中断功能。也就是说当一帧数据发送结束后,就会产生一个空闲中断。这样就可以利用这个空闲中断来判断一帧数据接收是否完成。 关于串口空闲检测可以在STM32参考手册上找到相关介绍 通过这个图可以看出来,当第一组数据Data1、Da
[单片机]
STM32单片机串口空闲<font color='red'>中断</font><font color='red'>接收</font>不定长数据
STM32开发笔记28: 中断请求的移植与处理
单片机型号:STM32L053R8T6 本文介绍如何移植STM32的IRQ(中断请求)到自己的系统中,我们以USART1接收中断为例。 先看启动文件(汇编语言),如下列程序所示,列出了其向量区,USART1的中断向量已用红色标识,当和USART1相关的中断发生时,程序指针(PC)在保护现场后,直接指向到该向量。 __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler
[单片机]
N76E003配置串口异步双工收发
串口收发 官方例程没有发现串口异步双工通信的例程,这里分享下异步双工通信(模式1,10位数据发送)的例程。 基本上不算全双工工作方式,因为发送时要禁用串口0中断(set_ES),会同时禁用收和发,也就是发送到发送完成这段时间没有串口接收中断。 初始化uart0时,TI(串口0发送中断标志位)必须要set,因为printf内部实现靠TI判断上一个字符发送完成。 #include string.h void usr_InitialUART0_Timer1_Mode1(UINT32 u32Baudrate) //T1M = 1, SMOD = 1 { P06_Quasi_Mode; //Setting UART
[单片机]
USART模块接收中断的问题处理
问题描述: 在使用USART做串口通讯时,我只把接收中断打开,并设置抢占优先级为最低一个级别,而接收中断上一个优先级处理事情比较多,可能占用了2ms时间。当我使用9600波特率往下位机发送数据,速度非常快,就是一直按回车发!问题就出来,不到1分钟时间,通讯没有反应了。USART配置代码如下: void uart_config(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = UART_GetBaud(BaudRate); USART_InitStructure.USART_WordLength =
[单片机]
USART模块<font color='red'>接收</font><font color='red'>中断</font>的问题处理
【stm8s003系列例程】2 基本串口收发(中断接收方式)
对于串口而言,最基本的就是 收发。 因为本例程系列及我个人的风格,我总是只让例程的功能——同时也就纯粹到 只展示这个功能的最小配置和最少代码。 而对我而言,串口 收发(1字节——因此也就不涉及另外 对 收发的缓冲处理 等 实质上 和 串口基本功能无关的 代码)。 当然大多数时候,我接收都是中断方式,而发送则无此必要——但是,我知道,在对速度有要求或者需要并行处理的场所,还需要 发送中断,但这个比较少用,因此不考虑。 下面是代码。 在贴以前,我讲一些对相关库,代码的改动。 首先,stm8s这个库,它的stm8s_uart1.c里,在计算波特率时,它需要获取当前时钟频率 它采用的是 CLK_GetClockFreq()
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved