mcu: STC89C52
晶振:11.0592M
显示的是AD7887转换后的AD值(2进制)
问题如下:
1、中断函数里添加 LCD1602_Clear();函数时,显示ad_time值正常,但显示temp1,temp2值却是一闪一闪的,数值是正确的,100变到99时正常
2、中断函数里注释掉 LCD1602_Clear();函数时,显示ad_time值,temp1,temp2值均会出现最后一位或后几位的0一直存在的现象
麻烦各位帮忙看下,程序如下:
- #include"Hardconfig.h"
- /**************************************************************************
- * 名 称: void LCD1602_Busy()
- * 功 能: 液晶屏忙碌检查
- * 说 明:
- * 输 入:
- * 输 出: 返回初始化的结果(0:不忙碌 1:忙碌)
- **************************************************************************/
- void LCD1602_Busy()
- {
- do
- {
- LCD_DATAPort=0xff;
- LCD_RS=0;
- LCD_RW=1;
- LCD_EN=0;
- LCD_EN=1;
- }
- while(BUSY);
- LCD_EN=0;
- }
- /**************************************************************************
- * 名 称: void LCD1602_Write_cmd(uchar cmd)
- * 功 能: 向LCD1602写指令
- * 说 明:
- * 输 入: cmd 要写入的指令值
- * 输 出:
- **************************************************************************/
- void LCD1602_Write_cmd(uchar cmd)
- {
- LCD1602_Busy();
- LCD_EN=0;
- LCD_RS=0;
- LCD_RW=0;
- LCD_DATAPort=cmd;
- _nop_();
- _nop_();
- LCD_EN=1;
- _nop_();
- _nop_();
- LCD_EN=0;
- }
- /**************************************************************************
- * 名 称: void LCD1602_Write_dat(uchar dat)
- * 功 能: 向LCD1602写数据
- * 说 明:
- * 输 入: dat 要写入的数据值
- * 输 出:
- **************************************************************************/
- void LCD1602_Write_dat(uchar dat)
- {
- LCD1602_Busy();
- LCD_EN=0;
- LCD_RS=1;
- LCD_RW=0;
- LCD_DATAPort=dat;
- _nop_();
- _nop_();
- LCD_EN=1;
- _nop_();
- _nop_();
- LCD_EN=0;
- }
- /**************************************************************************
- * 名 称: void LCD1602_Init()
- * 功 能: 初始化LCD1602
- * 说 明:
- * 输 入:
- * 输 出:
- **************************************************************************/
- void LCD1602_Init()
- {
- LCD1602_Write_cmd(0x38); // 16*2显示,5*7点阵,8位数据接口
- LCD1602_Write_cmd(0x0C); // 显示器开、光标开、光标允许闪烁
- LCD1602_Write_cmd(0x06); // 文字不动,光标自动右移
- LCD1602_Write_cmd(0x01); // 清屏
- }
- /**************************************************************************
- * 名 称: void LCD1602_Clear()
- * 功 能: 清屏
- * 说 明:
- * 输 入:
- * 输 出: 返回初始化的结果(0:复位成功 1:复位失败)
- **************************************************************************/
- void LCD1602_Clear()
- {
- LCD1602_Write_cmd(0x01);
- }
- /**************************************************************************
- * 名 称: uchar LCD1602_Disp_add(uchar row,uchar col)
- * 功 能: 设定lcd显示位置,即地址
- * 说 明: row 行坐标 1~2
- col 列坐标 1-16
- * 输 入: 行、列坐标
- * 输 出: 返回 0 修改失败
- 返回 1 修改成功
- ************************************************************************* */
- uchar LCD1602_Disp_add(uchar row,uchar col)
- {
- uchar address=0;
- if((row < 1) || (row > 2) || (col < 1) || (col > 16)) //判断参数合法性
- {
- return 0; //参数有误,直接返回
- }
- if(row==1) //把坐标转换成地址
- {
- address=col-1;
- }
- else if(row==2)
- {
- address=0x40+(col-1);
- }
- LCD1602_Write_cmd(0x80|address); //写入地址
- return 1;
- }
- /**************************************************************************
- * 名 称: void LCD1602_Disp_chr(uchar row, uchar col, uchar chr)
- * 功 能: 在特定的坐标写入字符
- * 说 明: row 行坐标 1~2 如果是0则不进行坐标改动
- col 列坐标 1-16 如果是0则不进行坐标改动
- chr 字符ASCII码
- * 输 入: uchar row, uchar col, uchar chr 例如:LCD1602_Disp_chr(1, 3,0x70)
- * 输 出:
- ************************************************************************* */
- void LCD1602_Disp_chr(uchar row, uchar col, uchar chr)
- {
- if((row != 0) && (col != 0)) //改动光标位置
- {
- if(!LCD1602_Disp_add(row, col))
- {
- return; //光标修改失败,直接返回
- }
- }
- LCD1602_Write_dat(chr); //写入字符
- }
- /**************************************************************************
- * 名 称: void LCD1602_Disp_string(uchar row, uchar col, uchar *str)
- * 功 能: 在特定的坐标写入字符串,没有换行功能
- * 说 明: row -- 行坐标 1~2, 如果是0则不进行坐标改动
- col -- 列坐标 1~16,如果是0则不进行坐标改动
- str -- 字符串地址
- * 输 入: uchar row, uchar col, uchar *str 例如:LCD1602_Disp_string(1, 3,"abcdefgh")
- * 输 出:
- ************************************************************************* */
- void LCD1602_Disp_string(uchar row,uchar col,uchar *str)
- {
- uchar count = 0;
- if((row != 0) && (col != 0)) //改动光标位置
- {
- if(!LCD1602_Disp_add(row, col))
- {
- return; //光标修改失败,直接返回
- }
- }
- while(*str!=' ') //写入字符串
- {
- LCD1602_Write_dat(*str);
- str++;
- count++; //这里用count计数,防止死循环
- if(count>16)
- {
- break;
- }
- }
- }
- /*********************************************************************
- * 名 称: void LCD1602_Disp_num(uchar row, uchar col, uint num)
- * 功 能: 在特定的坐标写入数字,没有换行功能
- * 说 明: row -- 行坐标 1~2, 如果是0则不进行坐标改动
- col -- 列坐标 1~16,如果是0则不进行坐标改动
- num -- 要显示的数字,范围0~9999
- * 输 入: uchar row, uchar col, uint num
- * 输 出:
- *********************************************************************/
- void LCD1602_Disp_num(uchar row, uchar col, uint num) //注意num的取值范围为0~65535
- {
- uchar str[5]; //保存num转换成的字符串
- uchar temp=0,i=0,count=0;
- uchar *p;
-
-
- //取得千位,转换成ASCII码存入str
- temp=num/1000;
- str[0]=temp+'0';
-
- //取得百位
- num= num - 1000 * temp;
- temp= num/100;
- str[1]= temp+'0';
-
- //取得十位
- num= num - 100 * temp;
- temp= num / 10;
- str[2]=temp+'0';
-
- //取得个位
- temp= num % 10;
- str[3]=temp+'0';
-
- //添加字符串结束标志
- str[4]=' ';
-
- //统计高位0的位数
- p=str;
- while(*p!=' ')
- {
- if(*p++=='0')
- {
- count++;
- }
- else
- {
- break;
- }
- }
-
- if(count==0)
- {
- //最高位不为0,不用处理
- }
- else if((count>0)&&(count<4))
- {
- for(i=0;i<(4-count);i++) //根据0的个数,将字符串左移count个
- {
- str[i]=str[i+count];
- }
- str[i]= ' ';
- }
- else if(count==4)
- {
- str[1]=' ';
- }
- LCD1602_Disp_string(row,col,str);
- }
-
复制代码
- /*****************************8位精度*******************************/
- /*********************************************************************
- * 名 称: uchar AD7887_READ_ONE_BYTE()
- * 功 能: 读取转换后的AD数据
- * 说 明: 前4位数据为引导位0 后8位数据位转换后的AD值 取高8位数据,丢弃最后4位
- * 输 入: 无
- * 输 出: Readvalue
- *********************************************************************/
- uchar AD7887_READ_ONE_BYTE()
- {
- uchar i,j,k;
- uchar Readvalue=0; //定义转换后的AD数值
- AD_CS=1;
- AD_SCLK=1;
- AD_DOUT=1;
- AD_DIN=1;
- AD_CS =0; //片选信号拉低
- AD_SCLK=1; //时钟保持一会 由于51单片机执行一条指令时间为1us,所以可以不做延时
-
- for(i=0;i<4;i++) //循环4次,跳过4位引导位
- {
- AD_SCLK=0;
- AD_SCLK=1;
- }
- for(j=0;j<8;j++) //读循环8次 刚好为一个字节
- {
- AD_SCLK=0; //时钟信号拉低
- Readvalue<<=1; //数据左移1位 先读高位,后读低位
- AD_SCLK=1; //时钟信号拉高
- if(AD_DOUT) //如果AD_DOUT输出高电平
- {
- Readvalue|=0x01; //将读到的数放在最低位,左移后变为高位
- }
- else
- {
- Readvalue&=0xfe; //否则将读到的数据置为0
- }
- }
- for(k=0;k<4;k++) //读循环4次 只产生时钟信号,不读数据
- {
- AD_SCLK=0;
- AD_SCLK=1;
- }
-
- AD_SCLK=1;
- AD_CS =1;
- return Readvalue; //返回读到的数据
- }
- /*********************************************************************
- * 名 称: uchar GetADCResult(uchar AD_Channel)
- * 功 能: 读取 uchar AD_Channel 通道的AD值
- * 说 明: 先写入要读取的通道(配置寄存器),然后读取数据
- * 输 入: AD7887_WRITE_ONE_BYTE();AD7887_READ_ONE_BYTE()
- * 输 出: ADCResult
- *********************************************************************/
- uchar GetADCResult(uchar AD_Channel)
- {
- uchar ADC_Result; //定义得到的转换结果 ADC_Result
- AD7887_WRITE_ONE_BYTE(AD_Channel); //配置寄存器为AD_Channel
- ADC_Result=AD7887_READ_ONE_BYTE(); //读取AD_Channel通道的转换数据 并将值赋给ADC_Result
- return ADC_Result;
- }
- /*******************滤波算法2****************************************
- * 名 称: uchar filter(uchar channel)
- * 功 能: 对uchar channel通道的AD值进行滤波处理
- * 说 明: 数据滤波函数 采用中位值平均滤波
- * 输 入: GetADCResult(channel)
- * 输 出: sum/(filter_N-2)
- *********************************************************************/
- uchar filter(uchar channel)
- {
- uint ADC_min, ADC_max, ADC_tmp, ADC_result, ADC;
- uchar i, j;
- ADC = 0;
- for(j = 0; j < 16; j++) //16为滤波强度
- {
- ADC_result = 0;
- ADC_min = ADC_max = GetADCResult(channel);
- for(i = 0; i < 8; i++)
- {
- ADC_tmp = GetADCResult(channel);
- if(ADC_tmp < ADC_min)
- {
- ADC_result += ADC_min;
- ADC_min = ADC_tmp;
- }
- else if(ADC_tmp > ADC_max)
- {
- ADC_result += ADC_max;
- ADC_max = ADC_tmp;
- }
- else
- {
- ADC_result += ADC_tmp;
- }
- }
- ADC_result /= 8;
- ADC += ADC_result;
- }
- ADC /= 16;
- return ADC;
- }
- void AD_Display1()
- {
-
- uchar temp1=0;
- temp1=filter(AD_Channel0); //将AD_Channel0通道读取到的值滤波后赋给temp1
- LCD1602_Disp_num(1,1,temp1); //将temp1值在LCD1602的第1行第一列开始显示
- // temp1=0;
- }
- void AD_Display2()
- {
- uchar temp2=0;
- temp2=filter(AD_Channel1); //将AD_Channel1通道读取到的值滤波后赋给temp2
- LCD1602_Disp_num(2,1,temp2); //将temp2值在LCD1602的第2行第一列开始显示
-
- // temp2=0;
- }
-
复制代码
- #include"STC89C5xRC.h"
- #include <intrins.h>
- #include "LCD1602.h"
- #include "AD7887.h"
- #include "Hardconfig.h"
- #define AD_Channel_0 0X31 //双通道工作 通道1 模式2 PM1=0 PM0=1 AD7887电源始终开启
- #define AD_Channel_1 0X39 //双通道工作 通道2 模式2 PM1=0 PM0=1 AD7887电源始终开启
- uint temp1=0,temp2=0;
- uint ad_time=0;
- uint ds_time=50000; //定时器定时时间
- /**********定时器0初始化***********/
- void Timer0Init(void)
- {
- TMOD &= 0xf0 ;
- TMOD |= 0x01 ; //定时器0工作方式1
- TH0=(65536-(FOSC/12)*ds_time)/ 256; //定时器重新赋初值
- TL0=(65536-(FOSC/12)*ds_time)% 256;
-
- TR0 = 1 ;
- ET0 = 1 ;
- }
-
- void main()
- {
- Timer0Init();
- EA = 1 ;
-
- Delay_us(100);
- LCD1602_Init();
- LCD1602_Clear();
- while(1)
- {
- }
- }
- /********** 定时器0中断**********/
- void Time0Isr(void) interrupt 1
- {
- TH0=(65536-(FOSC/12)*ds_time)/ 256; //定时器重新赋初值
- TL0=(65536-(FOSC/12)*ds_time)% 256;
- LCD1602_Clear();
- ad_time++;
-
- LCD1602_Disp_num(2,10,ad_time);
-
- temp1=filter(AD_Channel_0);
- LCD1602_Disp_num(1,1,temp1);
-
- temp2=filter(AD_Channel_1);
- LCD1602_Disp_num(2,1,temp2);
-
- }
复制代码
之前尝试过,但是1602驱动程序是网上下的,只是有些地方自己加了小改动,你说的那部分改过,但失败了,因为我不会指针
也尝试过在void LCD1602_Disp_num(uchar row, uchar col, uint num)里增加过清屏,但是直接不显示了,现在我再试试你说的方法,尝试着改下, 谢谢先
一周热门 更多>