高山入云 发表于 2023-3-6 12:25:27

STC8G1K08片子, 单个ADC 读时没问题,读两个ADC时就不行.试了...

STC8G1K08片子, 单个ADC 读时没问题,读两个ADC时就不行.试了一天都不成,百思不得其解,不知问题在哪?请帮助!
片子STC8G1K08 SOP16
用这个片子遇到几个问题,先是用串口时(串口用的定时器1),这时发现定时器0,不能用,否则 TR0 = 1开始计时,串口就不能通信!!!!不知为何?后来只好改用定时器2。
再后来就是ADC问题。发现 单独读时没问题,读两个时就不行,我这里读ADC0和ADC1。两个数据相同都是ADC1的数据。我怕在一起读出的问题,我再主程序里,设置延时分开读,隔一秒读AD0,再隔一秒读ADC1,都还不行。但发现上电第一次读取两个数据正常,之后再读,就不正常,之前12系列都没问题,这个8G折腾人!试了一天都不成,百思不得其解,不知问题在哪?请帮助!有朋友遇到的,请帮回复下,洗耳恭听!

//2023-03-01
//STC8G1K08 SOP16          33.1776MHz1T
//
///*************功能说明    **************
//使用P35,P36;P37输出3路PWM。 P37输出PWM1,P35,P36输出PWM2和PWM3.
//使用P10,P11输入ADC. 采集外部电位控制
//串口1配置为1200bps, 8,n, 1, 切换到P3.0 P3.1, 下载后就可以直接测试. 主时钟为33.1776MHZ,
//特别说明:串口1,必须用定时器1做波特率发生器;
//定时器0,不能用,否则 TR0 = 1开始计时,串口就不能通信!!!!不知为何?       pwm改选了定时器2.

//******************************************/

#include <STC8G.h>
#include<stdio.h>
#include<string.h>
#include<intrins.h>
//

typedef   unsigned char   u8;
typedef   unsigned int    u16;
typedef   unsigned long   u32;
//

/****************************** 串口 ***********************************/
u8 flag,m,i=0;
u8 Rx;
u8 fs;
void Timer2Init(void);
void UART1_init();
void UART1_TxByte(u8 dat);           //发送一个字节
void PrintString(u8 *puts); //发送一个字符串
//
///*************本地变量和声明    **************/
u8 t=0;
bit tmsflag=0;
u16 tms=0;


u8 ADCdim,ADCccm;
void ADC_init();
u16 ADCRead(u8 channel);

//
/********************主函数 **************************/
void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x03;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    UART1_init();

        Timer2Init();
       
        ADC_init();

    EA = 1;

    while (1)
        {
//       if(flag==1)   //先串口测试
//                {
//                flag=0;
//               PrintString("接收"); //发送一个字符串        "接收\r\n"               
//               UART1_TxByte(Rx);           //发送一个字节
//               UART1_TxByte(Rx);           //发送一个字节
//        
//                ADCdim=ADCRead(0) ;
////                if(ADCdim<5){P35=0;P36=0;        AUXR &= 0xef;}        else AUXR |= 0x10;
//                ADCccm=ADCRead(1) ;
//                UART1_TxByte(ADCdim);           //发送一个字节
//                UART1_TxByte(ADCccm);           //发送一个字节
////        ADCdim=Rx;            ADCccm=Rx;
//           }

                if(tms==20000)          //延时间隔长时间分开读取                  测试
                {       
                        ADCdim=ADCRead(0) ;                //读取ADC0
                        ADCdim=ADCRead(0) ;                //读取ADC0

                                PrintString("ok"); //发送一个字符串        "接收ok\r\n"
                                UART1_TxByte(ADCdim);           //发送一个字节
                }

                if(tmsflag==1)
                {        tmsflag=0;
                        ADCccm=ADCRead(1) ;           //读取ADC1
                        ADCccm=ADCRead(1) ;           //读取ADC1

                        if(ADCdim<3){P35=0;P36=0;        AUXR &= 0xef;}        else AUXR |= 0x10;
               

//                        UART1_TxByte(ADCdim);           //发送一个字节
                        UART1_TxByte(ADCccm);           //发送一个字节
           }
                  tms++; if(tms>40000) { tmsflag=1;tms=0;       }                   //延时测试

        }
}


//**************改定时器2 发送3PWM 信号********
void Timer2Init(void)                //1微秒@6.000MHz
{
        AUXR |= 0x04;        //定时器时钟1T模式
        T2L = 0xFF;                //设置定时初始值
        T2H = 0xFF;                //设置定时初始值
        AUXR |= 0x10;        //定时器2开始计时
        IE2 = 0x04;   //使能定时器中断
}

voidTM2_Isr() interrupt 12
{       
                if(t<ADCdim)P37=1; else P37=0;           //PWM1控制

                if(t<ADCccm)    P35=1; else P35=0;           //PWM2,PWM3控制
                if(t>ADCccm+2)        P36=1; //else P36=0;
                if(t>252) P36=0;
             t++;        if(t>=255)t=0;
}


////******ADC采集转换************************************************************

void ADC_init()
{   
        P1M0 = 0x00;                              //设置P1.0为ADC口
    P1M1 = 0x03;                                                                // 设置P1.0,P1.1为ADC口

    P_SW2 |= 0x80;
    ADCTIM = 0x3f;                              //设置ADC内部时序
   P_SW2 &= 0x7f;
    ADCCFG = 0x07;                              //设置ADC时钟为系统时钟/2/16        只取高8位结果
    ADC_CONTR = 0x80;                           //使能ADC模块
        _nop_(); _nop_(); _nop_(); _nop_();_nop_();   
//       EADC = 1;
}


u16 ADCRead(u8 channel)
{
    int res;
    ADC_CONTR = ADC_CONTR|channel|0xc0;         //启动AD转换
    _nop_();
    _nop_();
    while (!(ADC_CONTR & 0x20));                //查询ADC完成标志
    ADC_CONTR &= ~0x20;                         //清完成标志
//        UART1_TxByte(ADC_RES);       UART1_TxByte(ADC_RESL);
//res = (ADC_RES << 8) | ADC_RESL;            //读取ADC结果
        res = ADC_RES;                                                                //只取高8位结果
    return res;
        _nop_(); _nop_(); _nop_();
}


//******串口*****************

void UART1_init()                  //1200bps@33.1776MHz
{       
        SCON = 0x50;                //8位数据,可变波特率
        AUXR &= 0xBF;                //定时器时钟12T模式
        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                //设置定时器模式
        TL1 = 0xC0;                //设置定时初始值
        TH1 = 0xFD;                //设置定时初始值
        ET1 = 0;                //禁止定时器%d中断
        TR1 = 1;                //定时器1开始计时
        EA=1;
        ES=1;       
}

//===串口1发送。
bit B_TX1_Busy; //发送忙标志
void    UART1_TxByte(u8 dat)
{
    SBUF = dat;
    B_TX1_Busy = 1;
    while(B_TX1_Busy);
}

//========================================================================
// 函数: void PrintString1(u8 *puts)
// 描述: 串口1发送字符串函数。
// 参数: puts:字符串指针.
// 返回: none.
//========================================================================
void PrintString(u8 *puts) //发送一个字符串
{
    for (; *puts != 0;puts++)   UART1_TxByte(*puts);//遇到停止符0结束
}       

//=====串口1中断==================================================================
void com() interrupt4
{
        if(RI)
        {        RI=0;
                Rx=SBUF;i++;
                if(i>=2)
                {
                        flag=1;
                        i=0;
                }

//                m=SBUF;
//                fs=m;i++;
//                if(m=='a')
//                {
//                        flag=1;
//                        i=0;
//                }

        }

        if(TI)
    {
      TI = 0;
      B_TX1_Busy = 0;
    }
}

////*****定时器0 发送3PWM 信号 *****//定时器0开始计时,串口就不能通信!!!!
//void Timer0Init(void)                //1微秒@6.000MHz
//{
//        AUXR |= 0x80;                //定时器时钟1T模式
//        TMOD &= 0xF0;                //设置定时器模式
//        TL0 = 0xFf;                //设置定时初始值
//        TH0 = 0xFF;                //设置定时初始值
//        TF0 = 0;                //清除TF0标志
//        TR0 = 1;                //定时器0开始计时          打开时串口就不能通信!!!!
//}
//
//void TM0_Isr() interrupt 1
//{        if(t<ADCdim)       P37=1; else P37=0;
//        if(t<ADCccm)    P35=1; else P35=0;
//        if(t>ADCccm+2)        P36=1; //else P36=0;
//        if(t>252) P36=0;
//    t++;
//        if(t>=255)           t=0;
//}






梁工 发表于 2023-3-6 13:16:21

定时器都是独立的外设,不会受别的外设影响的,要仔细查下程序,或者用STC的官方例程测试。
只有一个ADC外设,通过多选1开关选择通道,所以基本不会出现单通道可以ADC、多通道不行的问题,出现了,基本是电路的问题。
刚在另一个论坛有人也做两路ADC说不行,其中一路ADC悬空,发现的“不正常”,这是典型的应用错误。
ADC输入悬空的通道,采样时,采样电容没法充放电,所以看似受上一个通道的影响。

高山入云 发表于 2023-3-6 13:23:49

梁工 发表于 2023-3-6 13:16
定时器都是独立的外设,不会受别的外设影响的,要仔细查下程序,或者用STC的官方例程测试。
只有一个ADC外 ...

两通道都有接电位控制器。问题是,如果程序里单独一路ADC没问题。
还有通过串口监视,上电第一次两个都正常,之后ADC1正常,ADC0就不正常,并且等于ADC1.很奇怪

高山入云 发表于 2023-3-6 13:26:16

梁工 发表于 2023-3-6 13:16
定时器都是独立的外设,不会受别的外设影响的,要仔细查下程序,或者用STC的官方例程测试。
只有一个ADC外 ...

还有,只要一开启定时器0,串口就不能收发了。

梁工 发表于 2023-3-6 13:40:36

高山入云 发表于 2023-3-6 13:26
还有,只要一开启定时器0,串口就不能收发了。

请仔细检查程序吧,定时器0跟串口一点关系都没有的。
ADC可以使用STC官方例程,直接下载HEX文件测试。

梁工 发表于 2023-3-6 13:49:43

这是ADC测试程序,请解压缩后直接下载“ADC相关程序-STC8G1K08-20PIN”里的“01-15路ADC转换-BandGap-串口1(P3.7)返回结果-C语言”里的HEX文件测试,串口返回结果,你只需要关心你要的通道即可,别的通道不用理会。下载时选择主频11.0592MHz,串口助手波特率115200,8,n,1. 文本接收。


高山入云 发表于 2023-3-6 13:55:55

梁工 发表于 2023-3-6 13:49
这是ADC测试程序,请解压缩后直接下载“ADC相关程序-STC8G1K08-20PIN”里的“01-15路ADC转换-BandGap-串口1 ...

好,谢谢。我试下

高山入云 发表于 2023-3-6 14:40:01

梁工 发表于 2023-3-6 13:49
这是ADC测试程序,请解压缩后直接下载“ADC相关程序-STC8G1K08-20PIN”里的“01-15路ADC转换-BandGap-串口1 ...

试了下,您的可以,我参考下您的程序。谢谢!

高山入云 发表于 2023-3-6 16:01:25

查看梁工的范例,终于解决了。谢谢梁工!
错在这一句:    ADC_CONTR = ADC_CONTR|channel|0xc0;         //启动AD转换
改为:ADC_CONTR = channel|0xc0;         //启动AD转换就好了。
上电第一次对的,那是因为通道值为0,当再读完第1口后,ADC_CONTR寄存器中的通道1值没有清除掉,所以才出现读第0口和第1口一样的结果.

神农鼎 发表于 2023-3-6 16:30:24

还是要用 STC-USB Link1D 来仿真STC8/STC32,这些问题就容易查到了


https://www.stcaimcu.com/forum.php?mod=viewthread&tid=752&extra=page%3D2



页: [1]
查看完整版本: STC8G1K08片子, 单个ADC 读时没问题,读两个ADC时就不行.试了...