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;
//}
定时器都是独立的外设,不会受别的外设影响的,要仔细查下程序,或者用STC的官方例程测试。
只有一个ADC外设,通过多选1开关选择通道,所以基本不会出现单通道可以ADC、多通道不行的问题,出现了,基本是电路的问题。
刚在另一个论坛有人也做两路ADC说不行,其中一路ADC悬空,发现的“不正常”,这是典型的应用错误。
ADC输入悬空的通道,采样时,采样电容没法充放电,所以看似受上一个通道的影响。 梁工 发表于 2023-3-6 13:16
定时器都是独立的外设,不会受别的外设影响的,要仔细查下程序,或者用STC的官方例程测试。
只有一个ADC外 ...
两通道都有接电位控制器。问题是,如果程序里单独一路ADC没问题。
还有通过串口监视,上电第一次两个都正常,之后ADC1正常,ADC0就不正常,并且等于ADC1.很奇怪 梁工 发表于 2023-3-6 13:16
定时器都是独立的外设,不会受别的外设影响的,要仔细查下程序,或者用STC的官方例程测试。
只有一个ADC外 ...
还有,只要一开启定时器0,串口就不能收发了。 高山入云 发表于 2023-3-6 13:26
还有,只要一开启定时器0,串口就不能收发了。
请仔细检查程序吧,定时器0跟串口一点关系都没有的。
ADC可以使用STC官方例程,直接下载HEX文件测试。 这是ADC测试程序,请解压缩后直接下载“ADC相关程序-STC8G1K08-20PIN”里的“01-15路ADC转换-BandGap-串口1(P3.7)返回结果-C语言”里的HEX文件测试,串口返回结果,你只需要关心你要的通道即可,别的通道不用理会。下载时选择主频11.0592MHz,串口助手波特率115200,8,n,1. 文本接收。
梁工 发表于 2023-3-6 13:49
这是ADC测试程序,请解压缩后直接下载“ADC相关程序-STC8G1K08-20PIN”里的“01-15路ADC转换-BandGap-串口1 ...
好,谢谢。我试下 梁工 发表于 2023-3-6 13:49
这是ADC测试程序,请解压缩后直接下载“ADC相关程序-STC8G1K08-20PIN”里的“01-15路ADC转换-BandGap-串口1 ...
试了下,您的可以,我参考下您的程序。谢谢! 查看梁工的范例,终于解决了。谢谢梁工!
错在这一句: ADC_CONTR = ADC_CONTR|channel|0xc0; //启动AD转换
改为:ADC_CONTR = channel|0xc0; //启动AD转换就好了。
上电第一次对的,那是因为通道值为0,当再读完第1口后,ADC_CONTR寄存器中的通道1值没有清除掉,所以才出现读第0口和第1口一样的结果. 还是要用 STC-USB Link1D 来仿真STC8/STC32,这些问题就容易查到了
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=752&extra=page%3D2
页:
[1]