搜索
bottom↓
回复: 12

请教printf用法的问题.试了一晚上也没找到原因

[复制链接]

出0入0汤圆

发表于 2010-11-21 20:11:56 | 显示全部楼层 |阅读模式
这是一个将AD转换的值通过串口发送到PC上的程序,但是弄了一晚上PC始终收不到程序,实在弄不明白了,来请教各位大师..谢谢各位!!单片机是STC12系列,1T的单片机.串口设置使用波特率计算软件算出来的,应该没有问题
#include"STC12C5620AD.H"           //STC12C54系列单片机头文件
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int

void uinit(void)                //9600bps@11.0592MHz
{
        PCON &= 0x7f;                //波特率不倍速
        SCON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
        AUXR &= 0xfe;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0f;                //清除定时器1模式位
        TMOD |= 0x20;                //设定定时器1为8位自动重装方式
        TL1 = 0xDC;                //设定定时初值
        TH1 = 0xDC;                //设定定时器重装值
        ET1 = 0;                //禁止定时器1中断
        TR1 = 1;                //启动定时器1
}


void delayms(uint xms)                               
{
        uint i,j;
        for(i=xms;i>0;i--)                      //i=xms即延时约xms毫秒
                for(j=110;j>0;j--);
}


void AD_Init()
{
        P1M0=0x0f;//0000 1111 设置P1口低4位为开漏模式,用来AD采集
        P1M1=0x0f;//0000 1111
        ADC_CONTR=0xe0;//1110 0000 开启AD转换器电源,设置最高转换速度
        delayms(100);
}


int GetAD(unsigned char channel) //channel为要取的通道号(0~7)
{
        unsigned char AD_finished=0;
        int result;
        ADC_CONTR|=channel;   //选择AD通道号
        ADC_CONTR|=0x08;      //启动AD转换
        while(AD_finished==0) //等待AD转换结束
        {
                AD_finished=(ADC_CONTR&0x10);//查询ADC_FLAG位是否置1
        }
        result=ADC_DATA*4+ADC_LOW2;//读走AD转换结果,由于ADC_DATA中存储12位中的
        //高8位,当要转换成10进制时,需将ADC_DATA中的数左移2位,即相当于*4
        ADC_CONTR&=0xf7;     //清除转换结束标志
        return (result);    //返回结果给函数
}


float Ad_Av(uchar channel)    //求100次采集电压的平均值
{
        float Val_Av=0;
        uchar num;
        for(num=100;num>0;num--)
        {
                Val_Av+=GetAD(channel);//100次采集求和
        }
        Val_Av/=100.0;            //求平均值
        Val_Av=Val_Av*5.0/1024;  //单片机电源为5V,求的真实电压值
        return (Val_Av);          //返回给函数
}


void main()
{
        float ad1,ad2,ad3,ad4;
        AD_Init();
        uinit();
        ad1=Ad_Av(1);
        ad2=Ad_Av(2);
        ad3=Ad_Av(3);
        ad4=Ad_Av(4);
        printf("The voltage is %fV\n",ad1);
        while(1);
}
这是一个将AD转换的值通过串口发送到PC上的程序,但是弄了一晚上PC始终收不到程序,实在弄不明白了,来请教各位大师..谢谢各位!!单片机是STC12系列,1T的单片机.串口设置使用波特率计算软件算出来的,应该没有问题.

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2010-11-22 19:18:38 | 显示全部楼层
原因找到了,程序如下.
#include"STC12C5620AD.H"           //STC12C54系列单片机头文件
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int


void init()
{
        SCON=0X40;
        REN=0;
        TMOD=0x20;
        TH1=0xfd;
        TL1=0xfd;
        TR1=1;
        TI=1;
        SM0=0;
        SM1=1;               
}


void delayms(uint xms)                               
{
        uint i,j;
        for(i=xms;i>0;i--)                      //i=xms即延时约xms毫秒
                for(j=110;j>0;j--);
}


void AD_Init()
{
        P1M0=0x0f;//0000 1111 设置P1口低4位为开漏模式,用来AD采集
        P1M1=0x0f;//0000 1111
        ADC_CONTR=0xe0;//1110 0000 开启AD转换器电源,设置最高转换速度
        delayms(100);
}


int GetAD(unsigned char channel) //channel为要取的通道号(0~7)
{
        unsigned char AD_finished=0;
        int result;
        ADC_CONTR|=channel;   //选择AD通道号
        ADC_CONTR|=0x08;      //启动AD转换
        while(AD_finished==0) //等待AD转换结束
        {
                AD_finished=(ADC_CONTR&0x10);//查询ADC_FLAG位是否置1
        }
        result=ADC_DATA*4+ADC_LOW2;//读走AD转换结果,由于ADC_DATA中存储12位中的
        //高8位,当要转换成10进制时,需将ADC_DATA中的数左移2位,即相当于*4
        ADC_CONTR&=0xf7;     //清除转换结束标志
        return (result);    //返回结果给函数
}


float Ad_Av(uchar channel)    //求100次采集电压的平均值
{
        float Val_Av=0;
        uchar num;
        for(num=100;num>0;num--)
        {
                Val_Av+=GetAD(channel);//100次采集求和
        }
        Val_Av/=100.0;            //求平均值
        Val_Av=Val_Av*5.0/1024;  //单片机电源为5V,求的真实电压值
        return (Val_Av);          //返回给函数
}


void main()
{
        while(1)
        {
                float ad1;//,ad2,ad3,ad4;
                init();
                AD_Init();
                ad1=Ad_Av(1);
            printf("voltage is %f\n",ad1);
                delayms(2000);
    }
}
原因有两点;1,串口初始化程序没有TI=1这一句,不知道为什么就不行,因为串口初始化是用STC的官方程序生成的.2,主函数有问题,主函数借鉴的郭天祥的程序.

(原文件名:电压表.jpg)

出0入0汤圆

发表于 2010-11-22 19:48:46 | 显示全部楼层
怎么查找错误????

出0入0汤圆

发表于 2010-11-22 19:49:02 | 显示全部楼层
为什么TI必须要置1,你打开putchar.c就知道了,看红字部分,如果可以的话,可以自己改一份:


/*
* putchar (full version):  expands '\n' into CR LF and handles
*                          XON/XOFF (Ctrl+S/Ctrl+Q) protocol
*/
char putchar (char c)  {

  if (c == '\n')  {
    if (RI)  {
      if (SBUF == XOFF)  {
        do  {
          RI = 0;
          while (!RI);
        }
        while (SBUF != XON);
        RI = 0;
      }
    }
    while (!TI);
    TI = 0;
    SBUF = 0x0d;                         /* output CR  */
  }
  if (RI)  {
    if (SBUF == XOFF)  {
      do  {
        RI = 0;
        while (!RI);
      }
      while (SBUF != XON);
      RI = 0;
    }
  }
   while (!TI);
  TI = 0;
  return (SBUF = c);
}

出0入0汤圆

发表于 2010-11-23 14:02:29 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2010-11-23 21:17:19 | 显示全部楼层
发现一个新问题.
#include"STC12C5620AD.H"           //STC12C54系列单片机头文件
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
void init()
{
    PCON &= 0x7f;                //波特率不倍速
        AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
        AUXR &= 0xfe;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0f;                //清除定时器1模式位
        SCON=0X40;                        //由此以上带有注释的串口初始化部分在12T模式11M晶振下可删除.
        REN=0;
        TMOD=0x20;
        TH1=0xed;                          //        12T 11.0592晶振模式下初始值为0Xfd
        TL1=0xed;
        TR1=1;
        TI=1;
        SM0=0;
        SM1=1;               
}
void delayms(uint xms)                               
{
        uint i,j;
        for(i=xms;i>0;i--)                      //i=xms即延时约xms毫秒
                for(j=110;j>0;j--);
}
void AD_Init()
{
        P1M0=0xff;//0000 1111 设置P1口低4位为开漏模式,用来AD采集
        P1M1=0xff;//0000 1111
        ADC_CONTR=0xe0;//1110 0000 开启AD转换器电源,设置最高转换速度
        delayms(100);
}
int GetAD(unsigned char channel) //channel为要取的通道号(0~7)
{
        unsigned char AD_finished=0;
        int result;
        ADC_CONTR|=channel;   //选择AD通道号
        ADC_CONTR|=0x08;      //启动AD转换
        while(AD_finished==0) //等待AD转换结束
        {
                AD_finished=(ADC_CONTR&0x10);//查询ADC_FLAG位是否置1
        }
        result=ADC_DATA*4+ADC_LOW2;//读走AD转换结果,由于ADC_DATA中存储12位中的
        //高8位,当要转换成10进制时,需将ADC_DATA中的数左移2位,即相当于*4
        ADC_CONTR&=0xf7;     //清除转换结束标志
        return (result);    //返回结果给函数
}
float Ad_Av(uchar channel)    //求100次采集电压的平均值
{
        float Val_Av=0;
        uchar num;
        for(num=100;num>0;num--)
        {
                Val_Av+=GetAD(channel);//100次采集求和
        }
        Val_Av/=100.0;            //求平均值
        Val_Av=Val_Av*5.0/1024;  //单片机电源为5V,求的真实电压值
        return (Val_Av);          //返回给函数
}
void main()
{
        while(1)
        {
                float ad1,ad2,ad3,ad0;
                init();
                AD_Init();
                ad0=Ad_Av(0);
                ad1=Ad_Av(1);
                ad2=Ad_Av(2);
                ad3=Ad_Av(3);
                printf("voltage0 is %f\n",ad0);
                delayms(2000);
                printf("voltage1 is %f\n",ad1);
                delayms(2000);
                printf("voltage2 is %f\n",ad2);
                delayms(2000);
    }
}
不知道郭天祥到底是怎么教的,书本上的程序到处是错误,在他的程序上加上printf,结果三个通道的值竟然是一样的(与通道0相同).又找了一晚上的原因,原来是因为第1,2,3通道在启动之前根本没有对AD进行初始化.
最后的程序改一下就可以了.
void main()
{
        while(1)
        {
                float ad1,ad2,ad3,ad0;
                init();
                AD_Init();
                ad0=Ad_Av(0);
                AD_Init();
                ad1=Ad_Av(1);
                AD_Init();
                ad2=Ad_Av(2);
                AD_Init();
                ad3=Ad_Av(3);
                printf("voltage0 is %f\n",ad0);
                delayms(2000);
                printf("voltage1 is %f\n",ad1);
                delayms(2000);
                printf("voltage2 is %f\n",ad2);
                delayms(2000);
    }
}

出0入0汤圆

发表于 2010-11-23 22:01:17 | 显示全部楼层
原来printf可以串口输出字符串???我那个晕菜啊~~~


才学到...记下~~~


我之前一直自己编写串口发送字符串的程序用的!!...~~~~

出0入0汤圆

发表于 2010-11-23 22:05:20 | 显示全部楼层
哎,对系统自带库函数完全不熟!~~

出0入0汤圆

 楼主| 发表于 2010-11-24 20:35:35 | 显示全部楼层
请教一下,如何通过AD转换出来的值计算VCC呢?比如1通道的电压是1.5V(精准电压),AD转换的结果是A,那么用什么公式计算出VCC呢?由于STC的基准是VCC,所以想要准确必须计算VCC电压.谢谢!!

出0入0汤圆

发表于 2011-8-13 17:24:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-8-22 14:48:16 | 显示全部楼层
呵呵 我也在解决这个问题

出0入0汤圆

发表于 2013-8-24 21:25:33 | 显示全部楼层
学习了,MARK一下

出0入0汤圆

发表于 2013-8-28 15:05:14 | 显示全部楼层
MARK
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 14:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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