找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12199|回复: 8
打印 上一主题 下一主题
收起左侧

关于新唐C51,N76E003此款芯片的定时器、ADC功能的使用备录

  [复制链接]
跳转到指定楼层
楼主
ID:326785 发表于 2018-5-11 21:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 黄进盛 于 2018-5-11 21:17 编辑

关于新唐C51,N76E003此款芯片的定时器、ADC功能的使用备录

使用方向:基于官方提供的Demo Code库(N76E003_BSP_Keil_C51_V1.0.5)

使用意图:使用N76E003的定时器功能,进行模拟时钟设计,ADC采集(注:没有使用时钟IC,个人只是单纯用来计时定时)

结果:功能已经实现。

个人项目经验总结:
        一、项目背景:基于新唐MCU (51)N76E003+LCM设计调试采集系统电压电流情况,记录相关项目过程经验从而进行后面的系统设计。

        二、项目模块与功能使用结果:1、定时器模块,2、ADC模块,3、中断模块;LCM液晶显示模块;按键模块。(备注:实现)

        三、项目样机图片:



四、项目程序开发记录:
        1、流程图:这里就不提供了,想必只有我这种单片机使用(能力水平:半桶水,哈哈)才要个流程图了。
        2、单独调试各个使用模块:ADC模块:以下是官方提供ADC的demo Code






官方提供了简单能用的参考代码,
以下是自己修改的多通道采集:
Uint32_t Get_ADC_Val(char channels)//获取ADC通道ADC值
{
        uint32_t ADC;
//        CKDIV=0x02;
        switch(channels)
        {
                case 4:
                        Enable_ADC_AIN4;        
               
                        break;

                case 5:
                        Enable_ADC_AIN5;
                        break;
               
                case 6:
                        Enable_ADC_AIN6;
                        break;
               
                case 7:
                        Enable_ADC_AIN7;
                        break;
        }
        clr_ADCF;
        set_ADCS;                                                                        // ADC start trig signal
  while(ADCF == 0);
        ADC=(ADCRH<<4)+ADCRL;
        clr_ADCF;
//        CKDIV=0x00;
        return ADC;        
}

小节总结:ADC的使用相信各位大神已经是使用的滚瓜烂熟了,我这种新手就不多提了,哈哈
附上一篇截图官方文档的ADC使用资料:



定时器模块:官方库中有各个定时器各个模式的sample Code附图:




简单附上定时器0模式1(部分执行代码)的官方代码:
/************************************************************************************************************
*    TIMER 1 interrupt subroutine
************************************************************************************************************/
void Timer1_ISR (void) interrupt 3  //interrupt address is 0x001B
{
    TH1 = u8TH1_Tmp;
    TL1 = u8TL1_Tmp;   

    P03 = ~P03;                     //P0.3 toggle when interrupt
}
/************************************************************************************************************
*    Main function
************************************************************************************************************/
void main (void)
{

    Set_All_GPIO_Quasi_Mode;
                TIMER0_MODE1_ENABLE;
                TIMER1_MODE1_ENABLE;

    clr_T1M;
    //set_T1M;

    u8TH0_Tmp = (65536-TH0_INIT)/256;
    u8TL0_Tmp = (65536-TL0_INIT)%256;   
    u8TH1_Tmp = (65536-TH1_INIT)/256;
    u8TL1_Tmp = (65536-TL1_INIT)%256;

    TH0 = u8TH0_Tmp;
    TL0 = u8TL0_Tmp;
    TH1 = u8TH1_Tmp;
    TL1 = u8TL1_Tmp;

    set_ET0;                                    //enable Timer0 interrupt
    set_ET1;                                    //enable Timer1 interrupt
    set_EA;                                     //enable interrupts
    set_TR0;                                    //Timer0 run
    set_TR1;                                    //Timer1 run
    while(1);
}

附上我自己(基于新唐官方库)修改后的使用定时器执行代码:

void Timer0_Init(void)//
{
        //TMOD = 0XFF;
        CKDIV=0X0C;
        TIMER0_MODE1_ENABLE;                   //Timer 0 and Timer 1 mode configuration
//        TIMER1_MODE2_ENABLE;
        clr_T0M;
    u8TH0_Tmp =TIMER_DIV12_VALUE_1ms>>8; //12分频初值
    u8TL0_Tmp =TIMER_DIV12_VALUE_1ms; //
        
          TH0 = u8TH0_Tmp;
    TL0 = u8TL0_Tmp;
        set_ET0;                                    //enable Timer0 interrupt
//set_ET1;                                    //enable Timer1 interrupt
        set_EA;                                     //enable interrupts
        set_TR0;                                    //Timer0 run
//set_TR1;                                    //Timer1 run
        CKDIV=0X00;
}

void Timer0_ISR (void) interrupt 1         
{        
          TH0 = u8TH0_Tmp;
    TL0 = u8TL0_Tmp;
        
        time_count++;
        key_handle=1;
        
        if(time_count==1000)
        {
                time_count=0;
    miao++;
    if(miao==60)
    {
      miao=0;
      fen++;
      if(fen==60)
      {
        fen=0;
        shi++;
        if(shi==24)
        {
          shi=0;
        }
       }
     }               
        }
        TF0=0;        
}

附上一张官方文档:




小节总结:官方提供的sample CODE 覆盖了整个定时器模块,给新人使用还是很有参考价值的,这次我也是第一次使用新唐的单片机,个人感觉还是挺方便的, N76E003  纯C51风格开发,(但就是定时器的使用让我思考起来人生),下载了官方库下来参考,看工程,咦!代码风格不一般,内设使用起来这么方便(库都已近定义好了),这不是Ctrl+c\Ctrl+v就能解决了吗!
这样新手 用起来就难堪了,我怎么调试定时中断时间都不对,难道是初值算错了,于是又找度娘,看看定时器初值怎么计算。改了改溢出值(还是不对,能力不够或者是解决问题的方向不对)于是又滑动鼠标滚轮看起了规格书(还好新唐的规格书是中文,不然就尴尬了)
规格书介绍的也挺简单的呀,看了看又调试,还是不行。于是又回到了官方库sample Code
附上一张官方库的文件图片:(提供的图片没什么用,就看看)




在官方库中的定时器模块没有找到解决方法。
哎,再仔细看看官方的库

有这么一个源文件:




看到有以下这些像是定时器的延时代码,想会不会是这些。
void Timer0_Delay100us(UINT32 u32CNT)
{
    clr_T0M;                                                //T0M=0, Timer0 Clock = Fsys/12
    TMOD |= 0x01;                                           //Timer0 is 16-bit mode
    set_TR0;                                                //Start Timer0
    while (u32CNT != 0)
    {
        TL0 = LOBYTE(TIMER_DIV12_VALUE_100us);        //Find  define in "Function_define.h" "TIMER VALUE"
        TH0 = HIBYTE(TIMER_DIV12_VALUE_100us);
        while (TF0 != 1);                                   //Check Timer0 Time-Out Flag
        clr_TF0;
        u32CNT --;
    }
    clr_TR0;                                                       //Stop Timer0
}
//------------------------------------------------------------------------------
void Timer0_Delay1ms(UINT32 u32CNT)
{
    clr_T0M;                                                //T0M=0, Timer0 Clock = Fsys/12
    TMOD |= 0x01;                                           //Timer0 is 16-bit mode
    set_TR0;                                                //Start Timer0
    while (u32CNT != 0)
    {
        TL0 = LOBYTE(TIMER_DIV12_VALUE_1ms);                 //Find  define in "Function_define.h" "TIMER VALUE"
        TH0 = HIBYTE(TIMER_DIV12_VALUE_1ms);
        while (TF0 != 1);                                   //Check Timer0 Time-Out Flag
        clr_TF0;
        u32CNT --;
    }
    clr_TR0;                                                //Stop Timer0
}

像延时一样,填上定时器初值看看定时中断对不对,调试又不对

TL0 = Timer0_Delay1ms(1);//1ms定时中断 初值
TH0 = Timer0_Delay1ms(1);
不对,,,,,,,还是不对。

再找找看看怎么解决,(又回到了下面的文件里,定时器初值的定义),填上去试试对不对,还是不对,呀呀呀呀呀。


仔细思考了一会,#define TIMER_DIV12_VALUE_1ms        65536-1334//1334*12/16000000 = 1 mS,                         // Timer divider = 12

这个初值是要对定时器模块进行相关的分频后的初值吗?
于是又看起了官方库,没有相关的定时器分频的使用参考呀,于是再回到了规格书:
找分频的使用介绍看看:附上图片:






看到这些资料,试试对定时器进行时钟分频调调看:于是就又了以下代码:


前面已经贴出,这里贴图片只做经验介绍总结。这里箭头和圈圈的就是我的解决方法了,定时器1ms中断实现了,时钟终于跑正常了,(对定时器进行12分频,才是正确附初值的正确方法)一天时间也就这样给没有了,这是新手的痛呀,时间宝贵。

注:以上图片以及代码只供个人经验交流总结使用,请勿做其他用途使用;个人使用总结,还请各位多多指教交流


总结.docx

958.13 KB, 下载次数: 64, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:342258 发表于 2018-5-31 16:10 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:266333 发表于 2018-6-1 14:21 | 只看该作者
DS_N76E003_SC_Rev1.05.pdf (8.47 MB, 下载次数: 18) NuTiny-SDK-N76E003开发板原理图V20.zip (2.15 MB, 下载次数: 22)
回复

使用道具 举报

地板
ID:93667 发表于 2018-7-16 17:27 | 只看该作者
谢谢分享经验
回复

使用道具 举报

5#
ID:214999 发表于 2018-7-17 15:05 | 只看该作者
感谢楼主分享
回复

使用道具 举报

6#
ID:317046 发表于 2018-9-10 09:46 | 只看该作者
楼主您好,我想咨询一下   Uint32_t Get_ADC_Val(char channels)//获取ADC通道ADC值   这个函数在主函数调用时他的实参时什么呢?
回复

使用道具 举报

7#
ID:332803 发表于 2018-9-12 08:43 | 只看该作者
谢谢分享经验
回复

使用道具 举报

8#
ID:400671 发表于 2018-10-27 14:21 | 只看该作者
谢谢分享经验
回复

使用道具 举报

9#
ID:195496 发表于 2022-11-10 10:14 | 只看该作者
Uint32_t Get_ADC_Val(char channels)//获取ADC通道ADC值
实参是采样哪一路通道
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表