前言
如果时间紧急可以直接看代码,代码有详细的注解!
(如果是准备去打合泰杯,以下内容就不用看了,评价是不如面向结果编程,吹牛吹的好听就可以,反正他们也不会看,也不懂。ps:或者让他们到你们学校举行就好,校赛嘛)
一、话不多说,先上代码
功能介绍:
通过AD转换采集光照强度,然后通过串口发送到电脑上显示出来。
引脚连接:
代码:
#include <HT66F2390.H>
#include <string.h>
#define fH 8000000 //单片机频率
#define BR 38400 //波特率
unsigned int ADvalue; //读取AD转换出来的数据
/**
* @brief 延时10us
* @param count 延时10us的次数,100 = 1ms--100 000 = 1s
* @retval 无
*/
void Delay_10us(unsigned long count)
{
volatile unsigned long i;
for(i=0;i<count;i++)
asm("nop");
}
//=============串口====================
void Uart_Init(void){
_pas1=0b11110000; //PA7为TX0功能、PA6为RX0功能
_u0cr1 = 0b10000000;
_u0cr2 = 0b11100100;
_brg0=fH/((unsigned long)16*BR)-1;
_ur0e = 1; //开启中断标志位
_mf5e=1;
_emi=1;
}
//发送一个单字符
void sendChar(const char s)
{
_txr_rxr0=s;
while(!_txif0);
}
//发送字符串
void sendString(const char* str)
{
unsigned char i = 0;
unsigned char length = strlen(str); // 使用正确的类型和拼写
for(i = 0; i < length; i++){
sendChar(str[i]); // 使用索引发送字符
}
}
//=====================================
//=============AD转换==================
/**
* @brief 初始化AD转换
* @param 无
* @retval 无
*/
void AD_Init(void)
{
//sadc0
//_sadc0 = 0xb0;
_sacs0 = 0;
_sacs1 = 0;
_sacs2 = 0;
_sacs3 = 0;//输入通道AN0(0000)--pc0
_adrfs = 1;//数据格式控制
_adcen = 1;//AD 转换器功能使能控制位
_adbz = 0;//A/D 转换忙标志位(0:AD 转换结束或未开始转换--1:AD 转换中)
_start = 1;//AD启动位---0->1->0 启动转换
//sadc1
//高四位:AD 转换器输入信号选择
//低三位:A/D 转换器时钟源选择位(此芯片系统时钟速度为8MHz,所以不能选择“000”,“001”或“111”)
//bit3:未定义,读为“0”
_sadc1 = 0x04;//0000 - 外部模拟通道输入ANn / 0100 - A/D 转换器时钟源选择位
//sadc2
_savrs0 = 0;
_savrs1 = 0;//AD 转换器参考电压选择(00:内部 AD 转换器电源 VDD)
//pcs0引脚共用
_pcs0 = 0x03;
}
/**
* @brief 读取AD转换的数据,并发送到串口上
* @param 无
* @retval 无
*/
void SendADValue(void)
{
_start = 0;//开始转换
while(_adbz);//如果标志位为1,等待转换
//ADvalue = (_sadoh << 8) | _sadol;//读取数据(可用于OLED显示等)
sendChar(_sadoh);//发送高位数据到串口
sendChar(_sadol);//发送低位数据到串口
_start = 1;//结束转换
Delay_10us(100);//1ms(防止单片机速度过快引起错误)
}
//=====================================
void main()
{
_wdtc = 0xaf;//关闭看门狗
Uart_Init();//串口初始化
AD_Init();//AD初始化
while(1)
{
SendADValue();
Delay_10us(300000);
}
}
//中断接收数据并返回数据
DEFINE_ISR(UART0,0x3C)
{
if(_ur0f == 1){
unsigned char rbuffer = 0;
while(!_rxif0);
rbuffer =_txr_rxr0;
sendChar(rbuffer);
}
_ur0f = 0;
}
二、相关AD寄存器配置
1、AD 转换用到的寄存器
AD 转换器的所有操作由六个寄存器控制。一对只读寄存器(SADOL,SADOH)用来存放 12-bit 的ADC 数据的值。剩下三个控制寄存器,即 SADC0,SADC1 和 SADC2 寄存器,用于设置 AD 转换器的操作和控制功能。但是主要是配置SADC0,SADC1 和 SADC2 寄存器,VBGRC一般不用配置。
还有一个引脚共用寄存器PCS0也要配置。
2、高字节寄存器 SADOH 和低字节寄存器SADOL
由于寄存器只使用了 16 位中 的 12 位,所以数据的存储于寄存器有两种方式,如图;其数据存储格式由 SADC0 寄存器的 ADRFS 位控制。
3、SADC0寄存器
(1)SACS0~SACS3
AD 转换器外部模拟输入通道选择位,可配置参数为0000~1111,对应AN0~AN15(共16个通道),在HT66F2390上与之对应的引脚是PC0~PC7、PD0~PD3、PH2~PH5。
本程序配置AN0通道,即0000,PC0引脚。
(2)ADRFS
AD 转换器数据格式控制位,配置高字节寄存器SADOH和低字节寄存器SADOL的数据存储格式。
0:A/D 转换器数据格式 → SADOH=D[11:4];SADOL=D[3:0]
1:A/D 转换器数据格式 → SADOH=D[11:8];SADOL=D[7:0]
(3)ADCEN
AD 转换器功能使能控制位,默认是使能的,1:使能 / 0:失能。置1将使能 AD 转换器;如果该位置0则关闭 AD 转换器以降低功耗,在关闭AD的时候SADOH 和 SADOL 的内容将保持不变。
(4)ADBZ
AD 转换忙标志位,用于判断是否完成AD转换的标志位,AD 转换结束后,此位被清零。
0:A/D 转换结束或未开始转换
(5)START
启动 AD 转换位,通常此位为低(0),如果再设为高(1)再被清零(0),将启动 A/D 转换过程。所以0→1→0启动 A/D 转换。
4、SADC1寄存器
(1)SAINS3~SAINS0
AD 转换器输入信号选择,可配置为0000~0111、10xx或者11xx(其中0000、0100、11xx是外部模拟通道输入--ANn(外部来源),10xx是接地,其他的为VDD和PGA及它们的分频)。一般都是配置为外部输入,转换传感器采集的数据。
如果选择内部模拟信号,无论 SACS 位段的值设定为多少,外部通道信号输 入将自动关闭。这是为了预防了外部通道输入与内部模拟信号连接从而导致的不可 预期的后果。
·(2)SACKS2~SACKS0
AD 转换器时钟源选择位,可配置为000~111。 A/D 时钟周期 tADCK 的范围为 0.5µs ~10µs,所以选择系统时钟速度时就必须谨慎。
如果系统时钟速度为8MHz时,SACKS2~SACKS0位不能设为“000”, “001”或“111”。否则所得的 A/D 时钟周期将小于最小时钟周期或大于最大时钟周期,导致所得 A/D 转换结果不准确。所以可以在去除“000”, “001”“111”后选择中间的时钟源,即“100”。
5、SADC2寄存器
SADC2寄存器主要配置SAVRS1~SAVRS0位(A/D 转换器参考电压选择),一般是配置为“00”内部 A/D 转换器电源 AV。
6、PCS0寄存器(引脚共用)
不配置该寄存器,默认为IO输出输入,要配置为AN0,只要配置共用引脚寄存器PCS01~PCS00位(PC0 引脚功能选择)为11即可。
三、代码解析
1、串口方面的函数可以参考
合泰杯HT66F2390——uart串口接收和发送_合泰串口接受数据-CSDN博客
2、AD_Init函数
配置AD相关寄存器和引脚共用寄存器的函数。
3、SendADValue函数
在函数中留有读取高字节寄存器SADOH和低字节寄存器SADOL的接口ADValue,可用于获取数据。在串口中分高低两位16进制的数据位发送到XCOM。
4、main主函数
首先关闭看门狗,避免重复复位。 Delay_10us(300000);是为了减低串口发送频率,方便观察实验结果。
5、警告
这个警告出现的原因是因为在主函数中使用了串口的发送函数sendChar,但是在实际的开发和应用中AD转换出来的数据一般不会频繁出现在主函数中,所以可以不用理会。(最后再说一句:ht就是使)
有问题可以私信我!