LM3S811开发板加入ADC测量后,1602显示异常

2019-03-24 08:21发布

用LM3S811开发板做了一个电源开关控制程序,LCD1602显示程序运行时间及当前的状态,这部分可以正常运行,但是后面在程序中加了ADC功能,用于检测继电器动作是否正常,加入ADC后,LCD1602中显示运行状态这一行出现了异常,表现为第一位显示字符一直在变化。其它字符应该变化时无刷新,DEBUG调试时,单步运行则显示正常,全速运行则出现问题,监视字符串内容,也确实是第一位字符一直在变化,2-4位内容为0D,其它字符正常,但显示无刷新。请各大神帮忙看看是哪里出问题了。代码如下:
#include <adc.h>
#include <stdio.h>
#define ADCSequEnable ADCSequenceEnable
#define ADCSequDisable ADCSequenceDisable
#define ADCSequConfig ADCSequenceConfigure
#define ADCSequStepConfig ADCSequenceStepConfigure
#define ADCSequDataGet ADCSequenceDataGet
tBoolean ADC_EndFlag = false; // 定义ADC转换结束的标志

#define  SCPEN         SysCtlPeripheralEnable         //使能外设语句太长

#define  RS               GPIO_PORTB_BASE,GPIO_PIN_0  //PB0为LCD命令口
#define  RW               GPIO_PORTB_BASE,GPIO_PIN_1  //PB1为LCD命令口
#define  EN               GPIO_PORTB_BASE,GPIO_PIN_2  //PB2为LCD命令口
#define  GPIO_WR    GPIOPinWrite     //简化库函数名
#define  GPIO_RD    GPIOPinRead      //简化库函数名
#define  GPIO_IN      GPIOPinTypeGPIOInput //简化库函数名,周立功中文库函数说明书中居然没有对应的说明
#define  GPIO_OUT   GPIOPinTypeGPIOOutput//简化库函数名,周立功中文库函数说明书中居然没有对应的说明
#define  LCD_DATA   GPIO_PORTD_BASE//lcd数据口
#define  CHAOSHENG_T        GPIO_PIN_3//PB3超声驱动,DYP-ME007是超声模块
#define  CHAOSHENG_R        GPIO_PIN_4//PB4超声状态接收  
#define  LED                    GPIO_PIN_0//PE0计数器捕获指示,每次捕获都取反
#define  RY                      GPIO_PIN_1//PE1继电器捕获指示,每次捕获都取反   
#define  LCD_BUSY                GPIO_PIN_7//PD7数据口第七位测LCD忙
#define  PWM_OUT                GPIO_PIN_5//PC5即CCP1=PWM输出   
#define  COUNT_IN                GPIO_PIN_6//PC6即CCP3=计数输入
#define  PWM_PORT              GPIO_PORTC_BASE
#define  COUNT_PORT           GPIO_PORTC_BASE
#define  LCD_PORT                GPIO_PORTB_BASE//PB0PB1PB2给液晶用,PB5未用,PB7给JTAG用,尽量避免作IO
#define  LED_PORT                GPIO_PORTE_BASE//PE0给蜂鸣器用,测试完成时提醒用
#define  RY_PORT                GPIO_PORTE_BASE//PE1给继电器用

#define  CHAOSHENG_PORT   GPIO_PORTB_BASE//PB3、PB4给超声用
/*=================================================================*/
unsigned long pinlv_vlue=1000;//产生的频率可在这里设置,1MHz误差10%,100KHz误差1.6%,10KHz误差0.1%,1KHz~92Hz没有误差,91以下显示0,没有深入研究。
unsigned long count_vlue=65535;//65535TIME1B计数器count从最大值开始向下计数
unsigned long systick_vlue=6000000;//6MHz晶振,1s
unsigned char systick_flag,echo_flag=0,count_flag;
unsigned char run_flag=0; //运行标志
unsigned long key_flag=0; //User按键按下次数计数
unsigned char string0[16]={"ACC:OFF  LOOP:01"};        //16个字符
unsigned char string2[16]={" T:             "};        //16个字符
unsigned long frequency,second=0;
unsigned long cycle=10;     //设定循环次数,实际循环次数+1
unsigned long T1=1;     // 140
unsigned long T2=2;     // 150
unsigned long T3=3;     //  210
unsigned long T4=4;     //  420
unsigned long T_t=5;     //480 试验周期总时间

unsigned long ulVal[];          //电压变量
unsigned char cBuf[30];          //电压串口输出字符串
void
UARTSend(const unsigned char *pucBuffer, unsigned long ulCount);
unsigned adcSample(unsigned long ulValue[]);
void put(const char *x);
/*============================延时===============================*/
void delay(unsigned long delay_clok_1us)//1us延时
{
    while(delay_clok_1us)delay_clok_1us--;
}
/*=======================测试LCD忙碌状态=========================*/
unsigned char LCD_check_busy(void)//测试LCD忙碌状态,返回字节型
{
    unsigned char busy;
    GPIO_WR(RS,0);         //RS=0
    GPIO_WR(RW,2);         //RW=1
    GPIO_WR(EN,4);         //EN=1
    GPIO_IN(LCD_DATA , 0XFF);           //设置数据口为输入        
    busy=GPIO_RD(LCD_DATA,LCD_BUSY)&0x80;//读取第八位忙闲标志        
    GPIO_OUT(LCD_DATA,0XFF);             //重新设置数据口为输出
    GPIO_WR(EN, 0);      //EN=0   
    return busy;           //返回检测信号
}
/*================为液晶LCD1602服务的函数===========================*/
void lcd_write(unsigned  char cd,unsigned  char temp)//写入到LCD
{   SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms   
    while(LCD_check_busy())        //cheker busy         加入后重新上电不工作
    SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms
        if(cd)GPIO_WR(RS, 1);   //当写数据时使RS=1
    else  GPIO_WR(RS, 0);   //当为写指令时RS=0      
    SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms
        GPIO_WR(RW, 0);
    SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms
        GPIO_WR(EN, 0);
    SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms
        GPIO_WR(LCD_DATA,0xFF,temp);//送数据到LCD
    SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms
        GPIO_WR(EN, 4);        // delay(4);//此延时必须要,不然不能显示
    SysCtlDelay(1*(TheSysClock/3000/2)); //约1ms
        GPIO_WR(EN, 0);      
}
/*================为液晶LCD1602服务的函数===========================*/
void lcd_strwdat( unsigned char x,unsigned char y,unsigned char *str)//准备显示内容
{            
    if(x<16)
        {if(y==0)
           x=0x80+x;
             else
           x=0xc0+x;
     lcd_write(0,x);
        }         //显示位置( x, y);
    while(*str!='')
        lcd_write(1,*str++);
}

/*===============User按键中断处理函数===============================*/
void GPIO_Port_C_ISR(void)
{
//unsigned char ucVal;
unsigned long ulStatus;
ulStatus=GPIOPinIntStatus(GPIO_PORTC_BASE,true);// get gpio c interrupt status
GPIOPinIntClear(GPIO_PORTC_BASE,ulStatus); // 清除中断状态
if(ulStatus&GPIO_PIN_4)//如果KEY的中断状态有效
        {
   //ucVal = GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_0); // 翻转LED
   //GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_0,~ucVal);
   key_flag++; //User键按下次数计数
  if(key_flag%2==0)
    run_flag=0;
   else
            run_flag=1;
            //lcd_write(0,0x02); delay(20);  //清屏
   SysCtlDelay(10*(SysCtlClockGet()/3000)); //延时约10ms,消除按键抖动
   while(GPIOPinRead(GPIO_PORTC_BASE,GPIO_PIN_4)==0x00);//等待KEY抬起
   SysCtlDelay(10*(SysCtlClockGet()/3000)); //延时约10ms,消除松键抖动

  }
}

/*====================定时器systick中断,每1秒===========================*/
void SysTick_ISR (void)//systick中断
{
     systick_flag=1;

}
/*==========================液晶始化init=======================*/
void LCD_UltraWave_init(void)//液晶初始化程序
{
    SCPEN(SYSCTL_PERIPH_GPIOB|SYSCTL_PERIPH_GPIOD);//端口使能声明
    //SysTickPeriodSet(systick_vlue);//设置SysTick初值,最大为16777216,用于计时
        SysTickPeriodSet(10000000);//设置SysTick初值,最大为16777216,用于计时
    SysTickEnable();     //启动SysTick
    SysTickIntEnable();  //systick系统定时器中断使能     
    GPIO_OUT(LCD_DATA,0xff);//设置LCD数据口(PD)全为输出
    GPIO_OUT(LCD_PORT,0x0f);//设置控制口(PB)低4位(LCD3位,超声模块1位)为输出
     SysCtlDelay(1*(TheSysClock/3000)); //约1ms   
        lcd_write(0,0x38); //delay(1);  //八位数据、双行显示、5X7点阵
     SysCtlDelay(1*(TheSysClock/3000)); //约1ms
        lcd_write(0,0x0C); //delay(1);  //显示开、关光标
    SysCtlDelay(1*(TheSysClock/3000)); //约1ms
        lcd_write(0,0x06); //delay(1);  //数据读、写操作后,地址指针AC自动增一
     SysCtlDelay(1*(TheSysClock/3000)); //约1ms
        lcd_write(0,0x01); //delay(1);  //清屏
}
/*==========================测试完成后显示及动作=======================*/
void test_finish(void)//测试完成后显示及动作程序
{  unsigned char string5[16]={"Wen Du Xun Huan "};        //16个字符
   unsigned char string6[16]={"TEST Finished   "};        //16个字符
   SysCtlDelay(100*(TheSysClock/3000)); //约1s
   //GPIO_WR(LED_PORT,LED,GPIO_RD(LED_PORT,LED)^LED);//翻转PE0,指示秒闪烁 (L7 GREEN LED)
   GPIO_WR(RY_PORT,RY,GPIO_RD(RY_PORT,RY)^RY);//翻转PE1,继电器动作
     while(1)
   {
            GPIO_WR(LED_PORT,LED,GPIO_RD(LED_PORT,LED)^LED);//翻转PE0,指示秒闪烁 (L7 GREEN LED) 可外加蜂鸣器用于声音提醒。
            lcd_strwdat(0,0,string5);    //显示第1行
     lcd_strwdat(0,1,string6);    //显示第2行
         lcd_write(0,0x08);                                           //字符闪烁
         SysCtlDelay(100*(TheSysClock/3000)); //约100ms
         lcd_write(0,0x0C);
         
   }

}

///*==========================串口初始化=======================*/  
void uartinit(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSet(UART0_BASE,115200,UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);
UARTEnable(UART0_BASE);
}
void put(const char *x)
{
while(*x!='')
{
  UARTCharPut(UART0_BASE,*(x++));
}
}

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    unsigned long ulStatus;
    ulStatus = UARTIntStatus(UART0_BASE, true);
    UARTIntClear(UART0_BASE, ulStatus);
    while(UARTCharsAvail(UART0_BASE))
    {
        UARTCharPutNonBlocking(UART0_BASE, UARTCharGetNonBlocking(UART0_BASE));
    }
}


// ADC初始化
void adcInit(void)
{
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC);        //使能ADC模块
        SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS); //设置ADC采样速率
        ADCSequenceDisable(ADC_BASE, 0);         // 配置前先禁止采样序列
        ADCSequenceConfigure(ADC_BASE,0,ADC_TRIGGER_PROCESSOR,0);  
        //配置ADC采样序列的触发事件和优先级:ADC基址,采样序列编号,触发事件,采样优先级
        ADCSequenceStepConfigure(ADC_BASE, 0, 0, ADC_CTL_CH0);
        ADCSequenceStepConfigure(ADC_BASE, 0, 1, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
        ADCIntEnable(ADC_BASE,0);        //使能ADC采样序列的中断
        IntEnable(INT_ADC0);                 // 使能ADC采样序列中断
        IntMasterEnable();                        // 使能处理器中断

        ADCSequenceEnable(ADC_BASE,0);                 // 使能一个ADC采样序列
}

// ADC采样
unsigned adcSample(unsigned long ulValue[])
{

        ADCProcessorTrigger(ADC_BASE, 0);         
        // 处理器触发采样序,调用ADCProcessorTrigger( )函数触发ADC采样

        while (!ADC_EndFlag)                          // 等待采样结束,加上后不能正确读出数据
        ADC_EndFlag = 1;                                 // 清除ADC采样结束标志
       
        ADCSequenceDataGet(ADC_BASE, 0, ulValue); // 读取ADC转换结果
        //return(ulValue);
}

// ADC采样序列0的中断
void ADC_Sequence_0_ISR(void)
{

unsigned long ulStatus;
        ulStatus = ADCIntStatus(ADC_BASE, 0, true);         // 读取中断状态
        ADCIntClear(ADC_BASE, 0);         // 清除中断状态,重要,等待下次AD中断
        if (ulStatus != 0)                         // 如果中断状态有效
        {
                ADC_EndFlag = 0;         // 置位ADC采样结束标志
        }
}

/*==========================主函数=================================*/
main(void) //
{       
    unsigned long x,w,v1,v2;
    unsigned long j,day,hour,mon,min;
    unsigned long loop=1;
        w=0;
        jtagWait();
        clockInit();
        uartinit();
        adcInit(); // ADC初始化
        SysCtlDelay(1*(TheSysClock/3000)); //1000倍时约1s
            SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC|SYSCTL_PERIPH_GPIOE);                         // 使能KEY、LED所在的PC端口
         GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);//配置PE0、PE1为输出
         GPIOPinIntEnable(GPIO_PORTC_BASE, GPIO_PIN_4);    //Enable GPIO C pin 4
         GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_4);// 设置KEY所在管脚PC4为输入
     GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_LOW_LEVEL);//set interrupt type is low Falling edge
         IntEnable(INT_GPIOC);//enable GPIO C interrupt
          LCD_UltraWave_init();//液晶+超声初始化
         SysCtlDelay(1*(TheSysClock/3000)); //1000倍时约1s
         w=0;
    while(1)
      {

            if(run_flag==1)
                    {
                          
          /*===================以下为每一个秒钟到达是的事件处理======================*/
           if(systick_flag==1)//systick中断标志,表示又一秒到
            {
            systick_flag=0;      
       /*===============================以下处理时钟==============================*/
                 w++;
             second=(w-1)/5;         //秒数加1
            adcSample(ulVal);              // ADC采样
                    v1 = (ulVal[0] * 3000) / 1024; // 转换成电压值
                        v2 = (ulVal[1] * 3000) / 1024; // 转换成电压值
                        sprintf(cBuf, "ADC0 = %ld(mV) ", v1); // 输出格式化
                        put(cBuf);
                        sprintf(cBuf, "ADC1 = %ld(mV) ", v2); // 输出格式化
                        put(cBuf);                 
             day=second/(60*60*24);
             hour=second/3600-day*24;       //取出小时
                         mon=second/60-day*24*60-hour*60;   //取出分钟
                 min=second/60-(loop-1)*T_t;                   //计算分钟,用于判定动作及计算循环数。倍数为周期分钟数
                     j=second-mon*60-hour*60*60-day*24*60*60;
                         
                                x=3;                     //左边空3个,在液晶的第五、六位显示小时
             string2[x++]=day/10+0x30;  //写入天的十位
             string2[x++]=day%10+0x30;  //写入天的个位
             string2[x++]=':';          //写入":"
             string2[x++]=hour/10+0x30;  //写入小时的十位
             string2[x++]=hour%10+0x30;  //写入小时的个位
             string2[x++]=':';         //写入":"
             string2[x++]=mon/10+0x30;  //写入分钟的十位
             string2[x++]=mon%10+0x30;  //写入分钟的个位
             string2[x++]=':';           //写入":"
             string2[x++]=j/10+0x30;      //写入秒钟的十位
             string2[x++]=j%10+0x30;      //写入秒钟的个位
                               
                               if ((min==T1 ||min==T3) && j==0 && w%5==0)                                                 //140,210
                                       {
                                               GPIO_WR(LED_PORT,LED,GPIO_RD(LED_PORT,LED)^LED);//翻转PE0,指示秒闪烁 (L7 GREEN LED)
                                                GPIO_WR(RY_PORT,RY,GPIO_RD(RY_PORT,RY)^RY);//翻转PE1,继电器动作
                                                string0[4]='O';  //写入天的十位
                                               string0[5]='N';  //写入天的十位
                                                string0[6]=' ';  //写入天的十位
                                               }
                                       if ((min==T2 ||min==T4 )&& j==0 && w%5==0)                                   //150,420
                                               {       
                                                      
                                                  GPIO_WR(LED_PORT,LED,GPIO_RD(LED_PORT,LED)^LED);//翻转PE0,指示秒闪烁 (L7 GREEN LED)
                                                  GPIO_WR(RY_PORT,RY,GPIO_RD(RY_PORT,RY)^RY);//翻转PE1,继电器动作
                                                 string0[4]='O';  //写入天的十位
                                                 string0[5]='F';  //写入天的十位
                                                 string0[6]='F';  //写入天的十位
                                               }
                         if(GPIOPinRead(GPIO_PORTE_BASE,GPIO_PIN_1)==0x00);
                                                 {
                                                                               
                                                 }

                                                if (min==T_t && j==0 && w%2==0)                           //min=周期                         480
                                               {        //SysCtlDelay(1000*(TheSysClock/3000)); //约1000ms
                                                       min=0;
                                                       loop++;
                                                        if(loop==cycle)           //LOOP设定为需要循环数+1
                                                         {
                               test_finish();                                                                 
                                                         }
                                                 else
                                                         {
                                                                 string0[14]=loop/10+0x30;  //写入天的十位
                                                       string0[15]=loop%10+0x30;  //写入天的个位
                                                         }                                                                
                                               }            

             //if(string2="   00:01:30:00  " or string2)

          /*=====================以下驱动液晶显示==============================*/

                         lcd_strwdat(0,0,string0);    //显示第1行
                         SysCtlDelay(1*(TheSysClock/3000)); //约1ms                          
             lcd_strwdat(0,1,string2);    //显示第2行
             }
        }
        else
                {        if(key_flag==0)
                                  {
                           lcd_strwdat(0,0,"Wen Du Xun Huan");    //显示第1行
                           lcd_strwdat(0,1,"User Key To Run");    //显示第2行
                                  }
                                  else
                                  {
                                   while(run_flag==0)
                                   {
                                   lcd_strwdat(0,0,"Test Pause      ");    //显示第1行
                           lcd_strwdat(0,1,"User Key To Run ");    //显示第2行
                                   lcd_write(0,0x08);                                           //字符闪烁
                                   SysCtlDelay(100*(TheSysClock/3000)); //约100ms
                                   lcd_write(0,0x0C);
                                           }
                                  }
                }
     }
}
/*===================================================================*/


此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
1条回答
academic
1楼-- · 2019-03-24 18:26
 精彩回答 2  元偷偷看……

一周热门 更多>

相关问题

    相关文章