- 基于STC8A8K64D4核心板
- keli5编写,11.0592频率下烧录
前言
STC8A8K64D4,它具有高速12位A/D转换器。其中16个管脚与ADC测量密切相关,其中15个为ADC外部测量通道,而1个则是用来获取出厂时校准的1.19V电压参考源的内部测量通道。据官方手册介绍,该芯片ADC的最快速度为每秒800K,每秒可进行80万次ADC转换。此外,内部电压参考源可用于反推测量未知外部电压。如需更详细信息,可查阅芯片手册以获取应用方法。本文章,只是介绍ADC获取和串口输出的基本应用。
现象
本文工程文件实现现象:直接输出ADC值,利用STC8A8K64D4核心板的P10做测试,有数值的时候是引脚浮空的时候,为0时是我用一根杜邦线将P10和GND连接,就数值就立马出来了。
过程
工程文件基本分成以下三大模块,库中都是些基本案例和注释,方便理解应用。
- ADC.h ADC应用调用库
- CK.h 串口调用库
- GPIO GPIO引脚模式切换库
-
mian.c
#include <STC8A8K64D4.H> #include <CK.H> #include "intrins.h" #include <ADC.H> #include <GPIO.H> void main() { CK_Init(); while(1) { //调用P10口读取ADC值 ADC_Use(0); } }
-
ADC.h
/* ADC库 基于STC8,11.0592频率下 功能:调用ADC */ /*ADC通道 0~7(P10~P17) 8~14(P00~P06) 15(测试内部1.19V) */ //ADC //参数channel: 范围:0~15(周期模式) 作用:ADC通道 void ADC_Use(unsigned char channel) { P_SW2|=0x80; ADCTIM=0x3f; P_SW2&=0x7f; ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16/16 ADC_CONTR = 0x80; ADC_CONTR = 0x80|channel; //使能ADC模块 ADC_CONTR |= 0x40; //启动AD转换 _nop_(); _nop_(); while (!(ADC_CONTR & 0x20)); //查询ADC完成标志 ADC_CONTR &= ~0x20; //清完成标志 //P2 = ADC_RES; //读取ADC结果 CK_SendIntX(ADC_RES); }
-
GPIO.h
/* GPIO库 基于STC8下 功能:单个,整组IO口引脚切换 */ /*官方文档介绍 I/O口工作模式 准双向口:(传统8051端口模式,弱上拉)灌电流可达20mA,拉电流为270~150uA(存在制造误差) 推挽输出:(强上拉输出,可达20mA,要加限流电阻) 高阻输入:(电不能流入也不能流出) 开漏输出:(Open-Drain) ,内部上拉电阻断开正在联网识别并翻译.开漏模式既可读外部状态也可对外输出(高电平或低电平)。 如要正确读外部状态或需要对外输出高电平,需外加上拉电阻,否则读不到外部状态,也对外输不出高电平。 */ //单个IO口模式切换 //参数io: 范围:1~XX(具体看有多少pin脚) 作用:单个IO口号 //参数mod: 范围:0~3 作用:模式 0:准双向口 1:推挽输出 2:高阻输入 3:开漏输出 //例如:P20要切换成推挽输出就是 GPIO_Mod(20,1); P30要切换成开漏输出就是 GPIO_Mod(30,3); void GPIO_Mod(unsigned char io,mod) { char ioa=io%10; char moda=mod%2; char modb=mod/2; switch(io/10) { case 0: P0M0=P0M0&((0x00|moda)<<ioa); P0M1=P0M1&((0x00|modb)<<ioa); break; case 1: P1M0=P1M0&((0x00|moda)<<ioa); P1M1=P1M1&((0x00|modb)<<ioa); break; case 2: P2M0=P2M0&((0x00|moda)<<ioa); P2M1=P2M1&((0x00|modb)<<ioa); break; case 3: P3M0=P3M0&((0x00|moda)<<ioa); P3M1=P3M1&((0x00|modb)<<ioa); break; case 4: P4M0=P4M0&((0x00|moda)<<ioa); P4M1=P4M1&((0x00|modb)<<ioa); break; case 5: P5M0=P5M0&((0x00|moda)<<ioa); P5M1=P5M1&((0x00|modb)<<ioa); break; case 6: P6M0=P6M0&((0x00|moda)<<ioa); P6M1=P6M1&((0x00|modb)<<ioa); break; case 7: P7M0=P7M0&((0x00|moda)<<ioa); P7M1=P7M1&((0x00|modb)<<ioa); break; } } //整组IO模式切换 //参数io: 范围:0~7(组) 作用:IO口组 //参数mod: 范围:0~3 作用:模式 0:准双向口 1:推挽输出 2:高阻输入 3:开漏输出 //例如:P1组要切换成推挽输出就是 GPIO_Mod(1,1); P3组要切换成开漏输出就是 GPIO_Mod(3,3); void GPIO_Mods(unsigned char io,mod) { char ioa=io%10; char moda=0x00; char modb=0x00; if(mod%2) moda=0xff; if(mod/2) modb=0xff; switch(io) { case 0: P0M0=moda; P0M1=modb; break; case 1: P1M0=moda; P1M1=modb; break; case 2: P2M0=moda; P2M1=modb; break; case 3: P3M0=moda; P3M1=modb; break; case 4: P4M0=moda; P4M1=modb; break; case 5: P5M0=moda; P5M1=modb; break; case 6: P6M0=moda; P6M1=modb; break; case 7: P7M0=moda; P7M1=modb; break; } }
-
CK.h
/* 简单串口通信库 .H文件通常用于配置 .C文件通常用于编写函数 说明:该库只是简单的应用串口1通信,和定时器1作为波特率发生器。方便调整程序。 功能:串口打印 使用说明:1.配置串口波特率,配置单片机运行频率 2.调用初始化函数 3.调用功能函数 层级:一级(为最底层无需在嵌套其他库) 标记:XY */ //基础 void CK_Init(); //串口1初始化 void CK_SendByte(char Data); //发送字节 //功能 void CK_SendInt(int num); //发送整型 void CK_SendIntX(int num); //发送整型(自动换行) void CK_SendFloat(float num); //发送浮点型 void CK_SendFloatX(float num); //发送浮点型(自动换行) void CK_SendStr(char *p); //发送字符串 void CK_SendStrX(char *p); //发送字符串(自动换行) void CK_Read(); //电脑发送数据给单片机又发回给电脑,
CK.c
#include <STC8.H> #include <CK.H> #include <stdio.H> #include "intrins.h" //配置工作环境 #define CK_Bti 115200 //配置串口波特率 #define CK_FOSC 11059200 //单片机运行频率(默认:11.0592 (频率x10^6)) #define CK_IntStrLen 20 //整型上限个数 #define CK_FloatStrLen 20 //浮点型型上限个数(默认保留三位小数) #define CK_BRT (65536 - CK_FOSC/ CK_Bti /4) bit CK_busy; //繁忙标志 char CK_rjs; //接收缓冲计数 char CK_ryjs; //接收阅读计数 char CK_buffer[16]; //接收缓冲 //串口初始化 void CK_Init() { SCON=0x50; //串口1控制寄存器 //串口1工作模式_模式1:可变波特率8位数据方式 and 允许串口接收数据 TMOD=0x00; //定时器模式寄存器 //定时器/计数器1工作模式:16位自动重载模式 TL1=CK_BRT; //定时器1计数寄存器(低位) TH1=CK_BRT>>8; //定时器1计数寄存器(高位) TR1=1; //定时器T1的运行控制位 //开始计数 AUXR=0x40; //辅助寄存器1 //定时器1速度控制位_CPU时钟不分频分频(FOSC/1) ES=1; //串口1中断开关 //打开 EA=1; //中断总开关 //打开 CK_rjs=0x00; CK_ryjs=0x00; CK_busy=0; } //发送字符串 void CK_SendStr(char *p) { while(*p) { CK_SendByte(*p++); } } //发送字符串(自动换行) void CK_SendStrX(char *p) { while(*p) { CK_SendByte(*p++); } CK_SendStr("\r\n"); } //发送整型 void CK_SendInt(int num) { char str[CK_IntStrLen]; sprintf(str,"%d",num); CK_SendStrX(str); } //发送整型(自动换行) void CK_SendIntX(int num) { char str[CK_IntStrLen]; sprintf(str,"%d",num); CK_SendStrX(str); } //发送浮点型 void CK_SendFloat(float num) { char str[CK_FloatStrLen]; sprintf(str,"%.3f",num); CK_SendStrX(str); } //发送浮点型(自动换行) void CK_SendFloatX(float num) { char str[CK_FloatStrLen]; sprintf(str,"%.3f",num); CK_SendStrX(str); } //发送字节 void CK_SendByte(char Data) { while (CK_busy); CK_busy = 1; SBUF = Data; } //串口1中断事件 分配寄存器组1 void UartIsr() interrupt 4 using 1 { if (TI) { TI = 0; CK_busy = 0; } if (RI) { RI = 0; CK_buffer[CK_rjs++] = SBUF; CK_rjs&=0x0f; //满16归0 } } //电脑发送数据给单片机又发回给电脑 void CK_Read() { if (CK_ryjs!=CK_rjs) { CK_SendByte(CK_buffer[CK_ryjs++]); CK_ryjs &= 0x0f; } }
总结
文章中的工程链接的分享:
链接:https://pan.baidu.com/s/1wrgfn7XZ4ci7c5qKE39hUw 提取码:w3s4