用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);
}
}
}
}
}
/*===================================================================*/
此帖出自
小平头技术问答
一周热门 更多>