打印

转 :实用的东西,关于ARM的一个小设计

[复制链接]
2630|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
6019实验室|  楼主 | 2009-12-20 10:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ARM, pi, se, ADC, AD
ESAYARM1138定时、中断、ADC(温度传感器)的综合应用(DIY)
最近在学ESAYARM1138,感觉比单片机要好用。做了个综合的小设计,在数码管上显示时间(由于找到的数码管是四位的,只能显示分和秒),用的是内部的16为定时器。在设计中开了个外部中断,用来切换时间的显示和温度的显示。

     温度传感器用的是lm1138内部的温度传感器,温度传感器特性图如下:


下载 (17.06 KB)
2009-8-11 11:22



温度算法:

10位的ADC模块集成有一个温度传感器,可以用来获取芯片的当前温度。

在温度传感器特性图里,给出了以下公式:

Vsenso = 2.7 - (T + 55) / 75,单位:V

设Vsenso对应的ADC采样值为N,2.7V对应N1,(T+55)/75对应N2

已知:

N1 * (3 / 1024) = 2.7

N2 * (3 / 1024) = (T + 55) / 75

由此得到:

N = N1 - N2 = 2.7 / (3 / 1024) - ((T + 55)/75) / (3 / 1024)

解得:

T = (151040 - 225 * N) / 1024

结论:

ADC配置为温度传感器模式后,只要得到ADC采样值N,就能推算出当前的温度T。

主程序:
  • #include  "systemInit.h"
  • #include  <adc.h>
  • #include  <stdio.h>
  • #include  <timer.h>
  • //  定义LED
  • #define  LED_PERIPH             SYSCTL_PERIPH_GPIOG
  • #define  LED_PORT               GPIO_PORTG_BASE
  • #define  LED_PIN                GPIO_PIN_2
  • //  定义KEY1和KEY2
  • #define  KEY1_PERIPH            SYSCTL_PERIPH_GPIOD
  • #define  KEY1_PORT              GPIO_PORTD_BASE
  • #define  KEY1_PIN               GPIO_PIN_1
  • //#define  KEY2_PERIPH            SYSCTL_PERIPH_GPIOG
  • //#define  KEY2_PORT              GPIO_PORTG_BASE
  • //#define  KEY2_PIN               GPIO_PIN_5
  • //    定义ADC
  • #define  ADCSequEnable          ADCSequenceEnable
  • #define  ADCSequDisable         ADCSequenceDisable
  • #define  ADCSequConfig          ADCSequenceConfigure
  • #define  ADCSequStepConfig      ADCSequenceStepConfigure
  • #define  ADCSequDataGet         ADCSequenceDataGet
  • tBoolean ADC_EndFlag = false;                               //  定义ADC转换结束的标志
  • int  min=0,sed=0,num=0,m=0;
  • int DATA_LED[10] =
  •   {
  •     //0~9的数码管段码
  • 0xC0,//"0"
  • 0xF9,//"1"
  • 0xA4,//"2"
  • 0xB0,//"3"
  • 0x99,//"4"
  • 0x92,//"5"
  • 0x82,//"6"
  • 0xF8,//"7"
  • 0x80,//"8"
  • 0x98,//"9"
  •   };
  • //  KEY1中断初始化
  • void key1IntInit(void)
  • {
  •     SysCtlPeriEnable(KEY1_PERIPH);                          //  使能KEY1所在的GPIO端口
  •     GPIOPinTypeIn(KEY1_PORT, KEY1_PIN);                     //  设置KEY1所在管脚为输出
  •     GPIOIntTypeSet(KEY1_PORT, KEY1_PIN, GPIO_LOW_LEVEL);    //  设置KEY1的中断类型
  •     IntPrioritySet(INT_GPIOD, 1 << 5);                      //  设置KEY1中断优先级为1
  •     GPIOPinIntEnable(KEY1_PORT, KEY1_PIN);                  //  使能KEY1所在管脚的中断
  •     IntEnable(INT_GPIOD);                                   //  使能GPIOD端口中断
  • }
  • /*
  • //  KEY2中断初始化
  • void key2IntInit(void)
  • {
  •     SysCtlPeriEnable(KEY2_PERIPH);                          //  使能KEY2所在的GPIO端口
  •     GPIOPinTypeIn(KEY2_PORT, KEY2_PIN);                     //  设置KEY2所在管脚为输出
  •     GPIOIntTypeSet(KEY2_PORT, KEY2_PIN, GPIO_LOW_LEVEL);    //  设置KEY2的中断类型
  •     IntPrioritySet(INT_GPIOG, 2<< 5);                      //  设置KEY2中断优先级为2
  •     GPIOPinIntEnable(KEY2_PORT, KEY2_PIN);                  //  使能KEY2所在管脚的中断
  •     IntEnable(INT_GPIOG);                                   //  使能GPIOG端口中断
  • }
  • */
  • void led()    //数码管显示及数据处理程序
  •   {
  • int  T0,T1,T2,T3;
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            T0=~DATA_LED[sed % 10];
  •            GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, T0); //个位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0xFF);
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            T1=~DATA_LED[sed / 10 ];
  •             GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF,T1 );//十位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0xFF);
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            T2=~DATA_LED[min % 10];
  •            GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF,T2 );//百位
  •            GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7,0xff );//百位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0xFF);
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            T3=~DATA_LED[min /  10];
  •            GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_3, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF,T3 );//千位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_3, 0xFF);
  •   }
  • //  ADC初始化
  • void adcInit(void)
  • {
  •     SysCtlPeriEnable(SYSCTL_PERIPH_ADC);                    //  使能ADC模块
  •     SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS);             //  设置ADC采样速率
  •     ADCSequDisable(ADC_BASE, 3);                            //  配置前先禁止采样序列
  •     //  采样序列配置:ADC基址,采样序列编号,触发事件,采样优先级
  •     ADCSequConfig(ADC_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
  •     //  采样步进设置:ADC基址,采样序列编号,步值,通道设置
  •     ADCSequStepConfig(ADC_BASE, 3, 0, ADC_CTL_TS |
  •                                       ADC_CTL_END |
  •                                       ADC_CTL_IE);
  •     ADCIntEnable(ADC_BASE, 3);                              //  使能ADC中断
  •     IntEnable(INT_ADC3);                                    //  使能ADC采样序列中断
  •     IntMasterEnable();                                      //  使能处理器中断
  •     ADCSequEnable(ADC_BASE, 3);                             //  使能采样序列
  • }
  • //  ADC采样
  • unsigned long adcSample(void)
  • {
  •     unsigned long ulValue;
  •     ADCProcessorTrigger(ADC_BASE, 3);                       //  处理器触发采样序列
  •     while (!ADC_EndFlag);                                   //  等待采样结束
  •     ADC_EndFlag = false;                                    //  清除ADC采样结束标志
  •     ADCSequDataGet(ADC_BASE, 3, &ulValue);                  //  读取ADC转换结果
  •     return(ulValue);
  • }
  • //  计算芯片温度值
  • unsigned char  tmpDisplay(unsigned long ulValue)
  • {
  •     unsigned long T;
  •     T= 151040UL - 225 * ulValue;
  •     T=T/1024;
  •     return(T);
  • }
  • //显示温度
  • void led2(int n)    //数码管显示及数据处理程序
  •   {
  • int  T0,T1;
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            T0=~DATA_LED[n % 10];
  •            GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, T0); //个位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0xFF);
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            T1=~DATA_LED[n / 10 % 10];
  •             GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF,T1 );//十位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0xFF);
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            //T2=~DATA_LED[min % 10];
  •            GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF,0X00 );//百位
  •            //GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7,0xff );//百位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0xFF);
  •     GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, 0xFF);
  •            //T3=~DATA_LED[min /  10];
  •            GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_3, 0x00);
  •            GPIOPinWrite(GPIO_PORTA_BASE, 0xFF,0X00 );//千位
  •     SysCtlDelay(1* (TheSysClock / 6000));    //  延时约0.5ms
  •     GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_3, 0xFF);
  • }
  • //  主函数(程序入口)

相关帖子

沙发
6019实验室|  楼主 | 2009-12-20 10:58 | 只看该作者
int main(void)



{



    jtagWait();                                             //  防止JTAG失效,重要!



    clockInit();                                            //  时钟初始化:晶振,6MHz



    adcInit();  



   



    unsigned long ulValue;



    int t;



    SysCtlPeriEnable(SYSCTL_PERIPH_GPIOA);                           //  使能LGPIO端口



    SysCtlPeriEnable(SYSCTL_PERIPH_GPIOB);     



    GPIOPinTypeOut(GPIO_PORTA_BASE, 0xFF);                     //  设置管脚为输出



    GPIOPinTypeOut(GPIO_PORTB_BASE, 0xFF);



   



  // IntPriorityGroupingSet(0);



    key1IntInit();                                          //  KEY1中断初始化



  //key2IntInit();                                          //  KEY2中断初始化



   



    SysCtlPeriEnable(SYSCTL_PERIPH_TIMER0);                 //  使能Timer模块



    TimerConfigure(TIMER0_BASE, TIMER_CFG_16_BIT_PAIR |     //  配置Timer为16位周期定时器



                                TIMER_CFG_A_PERIODIC);



    TimerPrescaleSet(TIMER0_BASE, TIMER_A, 99);             //  预先进行100分频



    TimerLoadSet(TIMER0_BASE, TIMER_A, 60000);              //  设置Timer初值,定时1s



    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);        //  使能Timer超时中断



    IntEnable(INT_TIMER0A);                                 //  使能Timer中断



    IntMasterEnable();                                      //  使能处理器中断



    TimerEnable(TIMER0_BASE, TIMER_A);                      //  使能Timer计数



   



    for (;;)



    {   



        m=num%2;



      if(m==0)



      {



       IntEnable(INT_TIMER0A);  



      TimerEnable(TIMER0_BASE, TIMER_A);



       led();



      }



      if(m==1)



      {



        ulValue = adcSample();                              //  ADC温度采样



        t= tmpDisplay(ulValue);



         led2(t);



      }  



    }



}



//  定时器的中断服务函数



void Timer0A_ISR(void)



{



    unsigned long ulStatus;



    ulStatus = TimerIntStatus(TIMER0_BASE, true);           //  读取中断状态



    TimerIntClear(TIMER0_BASE, ulStatus);                   //  清除中断状态,重要!



    if (ulStatus & TIMER_TIMA_TIMEOUT)                      //  如果是Timer超时中断



    {



         if(sed==59)



              {



                 if(min==59)



                {



            min=0;



          }



                   else



                     min++;



              sed=0;



              }



          else



              sed++;



     }



}



//  GPIOD的中断服务函数



void GPIO_Port_D_ISR(void)



{



   //  unsigned char ucVal;



    unsigned long ulStatus;



    ulStatus = GPIOPinIntStatus(KEY1_PORT, true);           //  读取中断状态



    GPIOPinIntClear(KEY1_PORT, ulStatus);                   //  清除中断状态,重要



    if (ulStatus & KEY1_PIN)                                //  如果KEY1的中断状态有效



    {



       num++;                                              //  中断服务函数



       /*



         ucVal = GPIOPinRead(LED_PORT, LED_PIN);             //  翻转LED



        GPIOPinWrite(LED_PORT, LED_PIN, ~ucVal);  



        */   



        SysCtlDelay(10 * (TheSysClock / 3000));             //  延时约10ms,消除按键抖动



        while (GPIOPinRead(KEY1_PORT, KEY1_PIN) == 0x00);     //  等待KEY抬起



        SysCtlDelay(10 * (TheSysClock / 3000));             //  延时约10ms,消除松键抖动



      



                                       



    }



   



}



/*



//  GPIOG的中断服务函数



void GPIO_Port_G_ISR(void)



{



    unsigned long ulStatus;



    ulStatus = GPIOPinIntStatus(KEY2_PORT, true);           //  读取中断状态



    GPIOPinIntClear(KEY2_PORT, ulStatus);                   //  清除中断状态,重要



   



    if (ulStatus & KEY2_PIN)                                //  如果KEY2的中断状态有效



    {



         if(sed==59)                                        //  中断服务函数



        {



            if(min==59)



        {



    min=0;



  }



      else



            min++;



              sed=0;



          }



    else



           sed++;   



     SysCtlDelay(10 * (TheSysClock / 3000));             //  延时约10ms,消除按键抖动



        while (GPIOPinRead(KEY2_PORT, KEY2_PIN) == 0x00);     //  等待KEY抬起



        SysCtlDelay(10 * (TheSysClock / 3000));             //  延时约10ms,消除松键抖动



    }



   



}



*/



//  ADC采样序列3的中断



void ADC_Sequence_3_ISR(void)



{



    unsigned long ulStatus;



    ulStatus = ADCIntStatus(ADC_BASE, 3, true);             //  读取中断状态



    ADCIntClear(ADC_BASE, 3);                               //  清除中断状态,重要



    if (ulStatus != 0)                                      //  如果中断状态有效



    {



        ADC_EndFlag = true;                                 //  置位ADC采样结束标志



    }



}
注:程序是我的原创,数码管部分用了两个显示函数主要是为了显示效果。上面的程序只是主程序,使用时只需要添加在工程模版中就可以了,不过要在工程模版中加入相应必要的文件。另外,在启动代码处要打开相应的中断(在工程模版中不会打开全部的中断,自己根据需要设置,这是我学习中发现的),否则程序无法实现其功能。

           实物贴图改天再贴出来。

使用特权

评论回复
板凳
huzixian| | 2009-12-20 20:40 | 只看该作者
好贴,顶

使用特权

评论回复
地板
NXP_PLC| | 2009-12-22 22:08 | 只看该作者
LZ,请注意,这里是NXP的论坛。
EASYARM1138板上用的MCU貌似是TI Lumi的吧。。。

使用特权

评论回复
5
虎虎生威| | 2009-12-23 16:35 | 只看该作者
看不了图片,是小叉叉啊

使用特权

评论回复
6
llljh| | 2009-12-23 16:35 | 只看该作者
看不了图片,是小叉叉啊
虎虎生威 发表于 2009-12-23 16:35

是你网速问题吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

121

主题

470

帖子

0

粉丝