找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 430|回复: 15
收起左侧

怎样把STC15F204EA单片机测量的电压从串口输出?

[复制链接]
ID:1100982 发表于 2023-11-24 10:11 | 显示全部楼层 |阅读模式
以下程序是把STC15F204EA单片机测量P1.3-P1.7几个管脚的电压得到V01-V05这5个电压,原来是发送到LCD1602显示的,现在想把这几个电压值组合成"V01,V02,V03,V04,V05;"这样的字符串发送到串口来显示。

现在串口可以显示u8 buf[11]="1,2,3,4,5;"的内容,尝试了很多次要把显示内容改为"V01,V02,V03,V04,V05;"都不成功,哪位高手能帮忙修改一下。


//本程序从串口发送字符串,单片机串口监控必须设置为9600bps

#define MAIN_Fosc                11059200L        //定义主时钟
#include        "STC15Fxxxx.H"

typedef bit BOOL;  //定义别名
typedef unsigned char BYTE;
typedef unsigned int WORD;

sbit RXB = P3^0; //??????
sbit TXB = P3^1;

#define BAUD 0xFE80 // 9600bps @ 11 .0592MHz

BYTE TBUF,RBUF;
BYTE TDAT,RDAT;
BYTE TCNT,RCNT;
BYTE TBIT,RBIT;
BOOL TING,RING;
BOOL TEND,REND;
BOOL CT;
BYTE t, r;
u8 buf[11]="1,2,3,4,5;"; //从串口发送的内容

/*************        本地变量声明        **************/

u16 Bandgap,Get_ADC(u8 channel),j;        //channel = 0~7

u8 m1,m2,m3,m4,stop=0,i;

u32 V0,V1,V2,V3,V4,V5,power,V01,V02,V03,V04,V05,V=1420;

sbit OUT=P3^4;         //15脚P3.4控制外部

u16        Get_ADC(u8 channel)        //channel = 0~7
{
        ADC_RES = 0;
        ADC_RESL = 0;

        ADC_CONTR = (ADC_CONTR & 0xE0) | 0x08 | channel;         //start the ADC
        NOP(4);

        while((ADC_CONTR & 0x10) == 0)        ;        //wait for ADC finish
        ADC_CONTR &= ~0x10;                //清除ADC结束标志
        return        (((u16)ADC_RES << 2) | (ADC_RESL & 3));
}

void ADC(X)
{
        P1ASF =1<<X;
        Get_ADC(X);        //通道改变, 先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
        for(j=0, i=0; i<16; i++)        {j+= Get_ADC(X);}
        j=j>>4;
}

void UART_INIT()
{
    TMOD = 0x00;
    AUXR = 0x80;
    TL0 = BAUD;
    TH0 = BAUD>>8;
    TR0 = 1;
    ET0 = 1;
    PT0 = 1;
    EA = 1;
    TING = 0;
    RING = 0;
    TEND = 1;
    REND = 0;
    TCNT = 0;
    RCNT = 0;
}

void main()
{     
        BYTE f=0;
    WORD e=0;
    UART_INIT();   //初始化串口
        ADC_CONTR = 0xE0;                        //90T, ADC power on
        

    while (1)
    {
                if (stop==0)
                {
                        ADC(2);                Bandgap = j;//TL431基准电压
               
                        ADC(3);                V1 = (u16)((u32)j*758/ Bandgap);
               
                        ADC(4);                V2 = (u16)((u32)j*1546/ Bandgap);
               
                        ADC(5);                V3 = (u16)((u32)j*2317/ Bandgap);
               
                        ADC(6);                V4 = (u16)((u32)j*3297/ Bandgap);
                        
                        ADC(7);                V5 = (u16)((u32)j*4050/ Bandgap);
               
                        V01=V1;
                        if(V2>V1){V02=V2-V1;}else{V02=0;}
                        if(V3>V1){V03=V3-V2;}else{V03=0;}
                        if(V4>V1){V04=V4-V3;}else{V04=0;}
                        if(V5>V1){V05=V5-V4;}else{V05=0;}
                }

                if(V01<V&&V02<V&&V03<V&&V04<V&&V05<V){}else{OUT=0;stop=1;}        //5块电池        
               

                TING = 1;
        TBUF = buf[f++];
        e=6000;
        while(e--);  //延时
        if (f>11){f=0;}
    }
}

void tm0() interrupt 1 using 1   
{
    if (RING)
    {
        if (--RCNT == 0)   //??---?????1
        {
            RCNT = 3;  
            if (--RBIT == 0)   //????????---????---??9?--8????---1????
            {
                RBUF = RDAT;   //?????
                RING = 0;   
                REND = 1;  
            }
            else//????9??????---????????--???
            {
                RDAT >>= 1;
                if (RXB)
                    RDAT |= 0x80;  //????????????0??1
            }
        }
    }
    else if (!RXB)
    {
        RING = 1;  
        RCNT = 4;  
        RBIT = 9;  
    }
    if (--TCNT == 0)  //??
    {
        TCNT = 3;  
        if (TING)  
        {
            if (TBIT == 0)//9???????
            {
                TXB = 0;   //?????
                TDAT = TBUF;  //??
                TBIT = 9;   //????????????8+1
                TEND = 0;  
            }
            else
            {
                TDAT >>= 1;   //??---??????
                if (--TBIT == 0)
                {
                    TXB = 1;
                    TING = 0;  
                    TEND = 1;  
                }
                else
                {
                    TXB = CY;  //CY????????7?
                }
            }
        }
    }
}

STC15F204EA串口实验.zip

44.23 KB, 下载次数: 3

回复

使用道具 举报

ID:213173 发表于 2023-11-24 13:26 | 显示全部楼层
无标题.jpg
  1. /*---------------------------------------------------------------------*/
  2. /* --- STC MCU Limited ------------------------------------------------*/
  3. /* --- STC15F4K60S4 系列 AD转换查询方式举例----------------------------*/
  4. /* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
  5. /* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
  6. /*---------------------------------------------------------------------*/

  7. //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
  8. //若无特别说明,工作频率一般为11.0592MHz


  9. #include "reg51.h"
  10. #include "intrins.h"

  11. #define FOSC    11059200L
  12. #define BAUD    115200

  13. typedef unsigned char BYTE;
  14. typedef unsigned int WORD;

  15. #define     URMD    0           //0:使用定时器2作为波特率发生器
  16.                                 //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
  17.                                 //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器

  18. sfr T2H   = 0xd6;               //定时器2高8位
  19. sfr T2L   = 0xd7;               //定时器2低8位

  20. sfr P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
  21. sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
  22. sfr P0M1 = 0x93;
  23. sfr P0M0 = 0x94;
  24. sfr P2M1 = 0x95;
  25. sfr P2M0 = 0x96;
  26. sfr P3M1 = 0xB1;
  27. sfr P3M0 = 0xB2;
  28. sfr P4M1 = 0xB3;
  29. sfr P4M0 = 0xB4;
  30. sfr P5M1 = 0xC9;
  31. sfr P5M0 = 0xCA;
  32. sfr P6M1 = 0xCB;
  33. sfr P6M0 = 0xCC;
  34. sfr P7M1 = 0xE1;
  35. sfr P7M0 = 0xE2;

  36. sfr  AUXR       =   0x8e;       //辅助寄存器                              

  37. sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
  38. sfr ADC_RES     =   0xBD;           //ADC高8位结果
  39. sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
  40. sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器

  41. #define ADC_POWER   0x80            //ADC电源控制位
  42. #define ADC_FLAG    0x10            //ADC完成标志
  43. #define ADC_START   0x08            //ADC起始控制位
  44. #define ADC_SPEEDLL 0x00            //540个时钟
  45. #define ADC_SPEEDL  0x20            //360个时钟
  46. #define ADC_SPEEDH  0x40            //180个时钟
  47. #define ADC_SPEEDHH 0x60            //90个时钟

  48. void InitUart();
  49. void InitADC();
  50. void SendData(BYTE dat);
  51. BYTE GetADCResult(BYTE ch);
  52. void Delay(WORD n);
  53. void ShowResult(BYTE ch);

  54. void main()
  55. {
  56.     P0M0 = 0x00;
  57.     P0M1 = 0x00;
  58.     P1M0 = 0x00;
  59.     P1M1 = 0x00;
  60.     P2M0 = 0x00;
  61.     P2M1 = 0x00;
  62.     P3M0 = 0x00;
  63.     P3M1 = 0x00;
  64.     P4M0 = 0x00;
  65.     P4M1 = 0x00;
  66.     P5M0 = 0x00;
  67.     P5M1 = 0x00;
  68.     P6M0 = 0x00;
  69.     P6M1 = 0x00;
  70.     P7M0 = 0x00;
  71.     P7M1 = 0x00;

  72.     InitUart();                     //初始化串口
  73.     InitADC();                      //初始化ADC
  74.     while (1)
  75.     {
  76.         ShowResult(0);              //显示通道0
  77.         ShowResult(1);              //显示通道1
  78.         ShowResult(2);              //显示通道2
  79.         ShowResult(3);              //显示通道3
  80.         ShowResult(4);              //显示通道4
  81.         ShowResult(5);              //显示通道5
  82.         ShowResult(6);              //显示通道6
  83.         ShowResult(7);              //显示通道7
  84.     }
  85. }

  86. /*----------------------------
  87. 发送ADC结果到PC
  88. ----------------------------*/
  89. void ShowResult(BYTE ch)
  90. {
  91.     SendData(ch);                   //显示通道号
  92.     SendData(GetADCResult(ch));     //显示ADC高8位结果

  93. //    SendData(ADC_LOW2);           //显示低2位结果
  94. }

  95. /*----------------------------
  96. 读取ADC结果
  97. ----------------------------*/
  98. BYTE GetADCResult(BYTE ch)
  99. {
  100.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  101.     _nop_();                        //等待4个NOP
  102.     _nop_();
  103.     _nop_();
  104.     _nop_();
  105.     while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
  106.     ADC_CONTR &= ~ADC_FLAG;         //Close ADC

  107.     return ADC_RES;                 //返回ADC结果
  108. }

  109. /*----------------------------
  110. 初始化串口
  111. ----------------------------*/
  112. void InitUart()
  113. {
  114.     SCON = 0x5a;                //设置串口为8位可变波特率
  115. #if URMD == 0
  116.     T2L = (65536 - (FOSC/4/BAUD));
  117.     T2H = (65536 - (FOSC/4/BAUD)) >> 8;
  118.     AUXR = 0x14;                //T2为1T模式, 并启动定时器2
  119.     AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
  120. #elif URMD == 1
  121.     AUXR = 0x40;                //定时器1为1T模式
  122.     TMOD = 0x00;                //定时器1为模式0(16位自动重载)
  123.     TL1 = (65536 - (FOSC/4/BAUD));
  124.     TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
  125.     TR1 = 1;                    //定时器1开始启动
  126. #else
  127.     TMOD = 0x20;                //设置定时器1为8位自动重装载模式
  128.     AUXR = 0x40;                //定时器1为1T模式
  129.     TH1 = TL1 = (256 - (FOSC/32/BAUD));
  130.     TR1 = 1;
  131. #endif
  132. }

  133. /*----------------------------
  134. 初始化ADC
  135. ----------------------------*/
  136. void InitADC()
  137. {
  138.     P1ASF = 0xff;                   //设置P1口为AD口
  139.     ADC_RES = 0;                    //清除结果寄存器
  140.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  141.     Delay(2);                       //ADC上电并延时
  142. }

  143. /*----------------------------
  144. 发送串口数据
  145. ----------------------------*/
  146. void SendData(BYTE dat)
  147. {
  148.     while (!TI);                    //等待前一个数据发送完成
  149.     TI = 0;                         //清除发送标志
  150.     SBUF = dat;                     //发送当前数据
  151. }

  152. /*----------------------------
  153. 软件延时
  154. ----------------------------*/
  155. void Delay(WORD n)
  156. {
  157.     WORD x;

  158.     while (n--)
  159.     {
  160.         x = 5000;
  161.         while (x--);
  162.     }
  163. }

复制代码



回复

使用道具 举报

ID:123289 发表于 2023-11-24 13:29 | 显示全部楼层
串口通讯是双方的事,先订立一个双共同遵守的协议,按协议发送数据就可以了。
如:协议中规定电压的表示方式,电压表的表示方式……
回复

使用道具 举报

ID:1100982 发表于 2023-11-24 14:03 | 显示全部楼层
yzwzfyz 发表于 2023-11-24 13:29
串口通讯是双方的事,先订立一个双共同遵守的协议,按协议发送数据就可以了。
如:协议中规定电压的表示方 ...

我觉得现在能发送字符串到串口而且能正确显示了,不是考虑协议的问题,而是怎样把发送的数据改为测量到的电压值。
回复

使用道具 举报

ID:161164 发表于 2023-11-24 14:21 | 显示全部楼层
用printf
回复

使用道具 举报

ID:1100982 发表于 2023-11-24 14:46 | 显示全部楼层

用过了printf了,但小白一个,不知还要引用什么库文件,编译通不过。
回复

使用道具 举报

ID:1100982 发表于 2023-11-24 14:51 | 显示全部楼层

试过这个程序直接写入STC15F204EA,串口甚至都没有接收到任何数据,我那个程序倒是能正常接收到“1,2,3,4,5;”这个字符串,一直不明白是怎么回事。
回复

使用道具 举报

ID:1100982 发表于 2023-11-24 14:53 | 显示全部楼层

不知还要引用哪个库,用reg51.h的话与STC15xxxx.H以有冲突。
回复

使用道具 举报

ID:161164 发表于 2023-11-24 15:55 | 显示全部楼层
y4h3z4 发表于 2023-11-24 14:53
不知还要引用哪个库,用reg51.h的话与STC15xxxx.H以有冲突。

用了STC15xxxx.H就不需要reg51.h了
printf要用stdio.h
https://blog.csdn.net/afeik/article/details/118356630
回复

使用道具 举报

ID:1004920 发表于 2023-11-24 17:05 | 显示全部楼层
是你没有把电压值赋值给buf【】
TBUF = buf[f++];
在这句的前面加上:
buf[0]=V1>>8;
buf[1]=V1;
buf[2]=V2>>8;
buf[3]=V2;
buf[4]=V3>>8;
buf[5]=V3;
buf[6]=V4>>8;
buf[7]=V4;
buf[8]=V5>>8;
buf[9]=V5;
回复

使用道具 举报

ID:883242 发表于 2023-11-24 17:13 | 显示全部楼层
自己写个转换程序,就两三行的代码,不要用printf,太大了浪费单片机资源。
回复

使用道具 举报

ID:1034262 发表于 2023-11-24 20:44 | 显示全部楼层
STC15F204EA没有硬件串口,用软件做一个,参考STC-ISP范例程序里的例子。
回复

使用道具 举报

ID:1100982 发表于 2023-11-25 06:23 来自手机 | 显示全部楼层
coody_sz 发表于 2023-11-24 20:44
STC15F204EA没有硬件串口,用软件做一个,参考STC-ISP范例程序里的例子。

原程序已经可以从串口接收到字符串了
回复

使用道具 举报

ID:1100982 发表于 2023-11-25 06:25 来自手机 | 显示全部楼层
zch5200 发表于 2023-11-24 17:05
是你没有把电压值赋值给buf【】
TBUF = buf[f++];
在这句的前面加上:

我原来就是不会赋值,你的回复是最接近我的问题的,等一下我试一下你的方法。
回复

使用道具 举报

ID:1100982 发表于 2023-11-25 22:22 | 显示全部楼层
zch5200 发表于 2023-11-24 17:05
是你没有把电压值赋值给buf【】
TBUF = buf[f++];
在这句的前面加上:

忘记说明了,V01、V02这些测量到的电压值是类似于1243的四位数,代表12.43V
程序开头定义:u8 buf[20]="01234567890123456789";
buf[0]=V01>>8;
buf[1]=V01;
得到的是空值,串口显示的是..?34567890123456789,前三位改变了,后面17位没有变化。

又参考原来LCD1602的显示方法,改为:
buf[0]='0'+V01/1000;
buf[1]='0'+(V01/100)%10;
buf[2]='0'+(V01/10)%10;
buf[3]='0'+V01%10;
buf[4]=','
终于正常显示了。

现在存在的问题是:u8 buf[23]还正常,可以发送24个字符
u8 buf[24]就报错
但是5组电压值,每组4位数字,各组之间要用“,”隔开,末尾用“;”结束,需要发送25个字符,刚好不够,怎么才能解决u8 buf[23]的限制,让发送的字符数不受限制呢?
找到原因了,是因为定义的变量太多。减少一些不必要的变量之后,u8 buf[30]都可以了。
回复

使用道具 举报

ID:1100982 发表于 2023-11-28 07:36 | 显示全部楼层
以下为正常运行的程序。


//本程序从串口发送字符串,单片机串口监控必须设置为9600bps

#define MAIN_Fosc                11059200L        //定义主时钟
#include        "STC15Fxxxx.H"

sbit RXB = P3^0;
sbit TXB = P3^1;

#define BAUD 0xFE80 // 9600bps @ 11 .0592MHz

/*************        本地变量声明        **************/
u8 TBUF,RBUF,TDAT,RDAT,TCNT,RCNT,TBIT,RBIT,t,r;
bit TING,RING,TEND,REND,CT;
u16 Bandgap,Get_ADC(u8 channel),j;        //channel = 0~7
u8 stop=0,i,buf[29]="-----------------------------"; //buf[]:从串口发送的内容;

u32 V0,V1,V2,V3,V4,V5,V01,V02,V03,V04,V05;

sbit OUT=P3^4;         //15脚P3.4控制外部

u16        Get_ADC(u8 channel)        //channel = 0~7
{
        ADC_RES = 0;        ADC_RESL = 0;

        ADC_CONTR = (ADC_CONTR & 0xE0) | 0x08 | channel;         //start the ADC
        NOP(4);

        while((ADC_CONTR & 0x10) == 0)        ;        //wait for ADC finish
        ADC_CONTR &= ~0x10;                //清除ADC结束标志
        return        (((u16)ADC_RES << 2) | (ADC_RESL & 3));
}

void ADC(X)
{
        P1ASF =1<<X;
        Get_ADC(X);        //通道改变, 先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
        for(j=0, i=0; i<16; i++)        {j+= Get_ADC(X);}
        j=j>>4;
}

void UART_INIT()
{
    TMOD = 0x00;
    AUXR = 0x80;
    TL0 = BAUD;
    TH0 = BAUD>>8;
    TR0 = 1;
    ET0 = 1;
    PT0 = 1;
    EA = 1;
    TING = 0;
    RING = 0;
    TEND = 1;
    REND = 0;
    TCNT = 0;
    RCNT = 0;
}

                 
void SENT(x,y) //x代表第几个电压值,y代表四位电压值,1243代表12.43V
{
        buf[x*6-6]='0'+y/1000;
        buf[x*6-5]='0'+(y/100)%10;
        buf[x*6-4]='.';
        buf[x*6-3]='0'+(y/10)%10;
        buf[x*6-2]='0'+y%10;
        if (x<5) {buf[x*6-1]=',';}
        else{buf[x*6-1]=';';}      //几个电压值之间用“,”隔开,末尾用“;”结束
}


void main()
{     
        u8 f=0;
    u16 e=0;
    UART_INIT();      //初始化串口
        ADC_CONTR = 0xE0; //90T, ADC power on
       

    while (1)
    {
                if (stop==0)
                {
                        ADC(2);                Bandgap = j;//TL431基准电压
               
                        ADC(3);                V1 = (u16)((u32)j*758/ Bandgap);
               
                        ADC(4);                V2 = (u16)((u32)j*1546/ Bandgap);
               
                        ADC(5);                V3 = (u16)((u32)j*2317/ Bandgap);
               
                        ADC(6);                V4 = (u16)((u32)j*3297/ Bandgap);
                       
                        ADC(7);                V5 = (u16)((u32)j*4050/ Bandgap);
               
                        V01=V1;
                        if(V2>V1){V02=V2-V1;}else{V02=0;}
                        if(V3>V1){V03=V3-V2;}else{V03=0;}
                        if(V4>V1){V04=V4-V3;}else{V04=0;}
                        if(V5>V1){V05=V5-V4;}else{V05=0;}
                }

               
                SENT(1,V01);SENT(2,V02);SENT(3,V03);SENT(4,V04);SENT(5,V05); //电压值转换为数组字符,准备发送到串口

                TING = 1;
        TBUF = buf[f++];
        e=6000;
        while(e--);  //延时
        if (f>29){f=0;}
    }
}

void tm0() interrupt 1 using 1   
{
    if (RING)
    {
        if (--RCNT == 0)
        {
            RCNT = 3;  
            if (--RBIT == 0)
            {
                RBUF = RDAT;
                RING = 0;   
                REND = 1;  
            }
            else
            {
                RDAT >>= 1;
                if (RXB)
                    RDAT |= 0x80;
            }
        }
    }
    else if (!RXB)
    {
        RING = 1;  
        RCNT = 4;  
        RBIT = 9;  
    }
    if (--TCNT == 0)
    {
        TCNT = 3;  
        if (TING)  
        {
            if (TBIT == 0)
            {
                TXB = 0;
                TDAT = TBUF;
                TBIT = 9;
                TEND = 0;  
            }
            else
            {
                TDAT >>= 1;
                if (--TBIT == 0)
                {
                    TXB = 1;
                    TING = 0;  
                    TEND = 1;  
                }
                else
                {
                    TXB = CY;
                }
            }
        }
    }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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