STC8G1K08A学习方法
各位大佬,有没有什么方法可以看懂单片机的数据手册,里面的内容太抽象了,看前面忘后面。想实现具体功能,却无从下手,不知道各个寄存器之间的联系。
比如ADC的电压采集,也找不到具体的例子。
就是要看数据手册啊,从这里看起。
你要学 ADC 就看 ADC的章节吧。
点进去就可以看那个章节,然后跟着他的案例程序运行就可以了。
<font size="3">/*
16.6 范例程序
16.6.1 ADC 基本操作(查询方式)
C 语言代码
*/
//测试工作频率为11.0592MHz
#include "reg51.h"
#include "intrins.h"
sfr ADC_CONTR = 0xbc;
sfr ADC_RES = 0xbd;
sfr ADC_RESL = 0xbe;
sfr ADCCFG = 0xde;
sfr P_SW2 = 0xba;
#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P1M0 = 0x00; //设置P1.0 为ADC 口
P1M1 = 0x01;
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC 内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置ADC 时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能ADC 模块
while (1)
{
ADC_CONTR |= 0x40; //启动AD 转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询ADC 完成标志
ADC_CONTR &= ~0x20; //清完成标志
P2 = ADC_RES; //读取ADC 结果
ADCCFG = 0x00; //设置结果左对齐
ACC = ADC_RES; //A 存储ADC 的10 位结果的高8 位
B = ADC_RESL; //B存储ADC 的10 位结果的低2 位,B为0
// ADCCFG = 0x20; //设置结果右对齐
// ACC = ADC_RES; //A存储ADC 的10 位结果的高2 位,A为0
// B = ADC_RESL; //B 存储ADC 的10 位结果的低8 位
}
}
</font>
<font size="3">
/*
16.6.4 利用ADC 第15 通道测量外部电压或电池电压
STC8G 系列ADC 的第15 通道用于测量内部参考信号源,由于内部参考信号源很稳定,约为1.19V,
且不会随芯片的工作电压的改变而变化,所以可以通过测量内部1.19V 参考信号源,然后通过ADC 的
值便可反推出外部电压或外部电池电压。
下图为参考线路图:
C 语言代码
*/
//测试工作频率为11.0592MHz
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
sfr AUXR = 0x8e;
sfr ADC_CONTR = 0xbc;
sfr ADC_RES = 0xbd;
sfr ADC_RESL = 0xbe;
sfr ADCCFG = 0xde;
sfr P_SW2 = 0xba;
#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
int *BGV; //内部1.19V 参考信号源值存放在idata 中
//idata 的EFH 地址存放高字节
//idata 的F0H 地址存放低字节
//电压单位为毫伏(mV)
bit busy;
void UartIsr() interrupt 4
{
if (TI)
{
TI = 0;
busy = 0;
}
if (RI)
{
RI = 0;
}
}
void UartInit()
{
SCON = 0x50;
TMOD = 0x00;
TL1 = BRT;
TH1 = BRT >> 8;
TR1 = 1;
AUXR = 0x40;
busy = 0;
}
void UartSend(char dat)
{
while (busy);
busy = 1;
SBUF = dat;
}
void ADCInit()
{
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC 内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x2f; //设置ADC 时钟为系统时钟/2/16
ADC_CONTR = 0x8f; //使能ADC 模块,并选择第15 通道
}
int ADCRead()
{
int res;
ADC_CONTR |= 0x40; //启动AD 转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询ADC 完成标志
ADC_CONTR &= ~0x20; //清完成标志
res = (ADC_RES << 8) | ADC_RESL; //读取ADC 结果
return res;
}
void main()
{
int res;
int vcc;
int i;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
BGV = (int idata *)0xef; //内部1.19V 参考信号源值存放在idata 中
ADCInit(); //ADC 初始化
UartInit(); //串口初始化
ES = 1;
EA = 1;
// ADCRead();
// ADCRead(); //前两个数据建议丢弃
res = 0;
for (i=0; i<8; i++)
{
res += ADCRead(); //读取8 次数据
}
res >>= 3; //取平均值
vcc = (int)(1024L * *BGV / res); //(10 位ADC 算法)计算VREF 管脚电压,即电池电压
// vcc = (int)(4096L * *BGV / res); //(12 位ADC 算法)计算VREF 管脚电压,即电池电压
//注意,此电压的单位为毫伏(mV)
UartSend(vcc >> 8); //输出电压值到串口
UartSend(vcc);
while (1);
}
/*
上面的方法是使用ADC 的第15 通道反推外部电池电压的。在ADC 测量范围内,ADC 的外部测量
电压与ADC 的测量值是成正比例的,所以也可以使用ADC 的第15 通道反推外部通道输入电压,假设
当前已获取了内部参考信号源电压为BGV,内部参考信号源的ADC 测量值为resbg,外部通道输入电压
的ADC 测量值为resx,则外部通道输入电压Vx=BGV / resbg * resx;
*/
</font>
angmall 发表于 2023-9-7 12:18
就是要看数据手册啊,从这里看起。
你要学 ADC 就看 ADC的章节吧。
谢谢,你发的程序有注释说明,所以理解起来要好一点。
市面上不知道有没有类似像大话数据结构这样的书籍,可以通俗易懂的讲解单片机。 你好,我使用一枚3s电池,参考上面的代码写出来之后,返回的电压值是5816(mv),而正常电压应该为12000(mv)左右,请问这个程序检测的电压值是有上限的吗 先学习下 郭天祥 老师讲的 ADC 部分
然后再看自己用的 MCU 的数据手册,毕竟不完全相同
提高篇10-5-利用STC8H单片机内部1.19V信号源反推电源电压-郭天祥老师-STC单片机教学视频 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
页:
[1]