本帖最后由 芯圣电子官方QQ 于 2023-7-19 16:40 编辑
上次搞PCF8591,只搞好了DAC,没搞好ADC。
这次把ADC搞好了。
SCL接P01,SDA接P00。把ADC值通过串口打印出来,可是有点毛病,打印的有时候会漏掉几个字符,搞不懂。
串口发送接P24。
代码:
#define ALLOCATE_EXTERN
#include "HC89S105AC8.h"
#include "i2c.h"
#define uint8_t unsigned char
#define uint16_t unsigned int
#define PCF8591 0x90 //PCF8591 地址
#define SCL P0_1 //I2C时钟控制位
#define SDA P0_0
unsigned char AD_CHANNEL;
unsigned char DAC_VALUE=0;
unsigned char ADCVALUE=0;
unsigned char txBuf[]={"ADC VALUE=: \r\n"};
// 函数申明
void delay(uint i);
/***************************************************************************************
* @说明 IIC发送一个字节的数据
* @参数 fuc_Add:存储的地址
* fuc_Dat:存储的数据
* @返回值 无
* @注 无
***************************************************************************************/
void DACconversion(unsigned char fuc_Add, unsigned char fuc_Dat)
{
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x20; //起始位发送起始信号
while ((!(IICCON & 0x08)) && (IICSTA != 0x08));
IICCON &= ~0x20; //起始位停止起始信号
IICCON &= ~0x08; //清除中断标志位
IICDAT = PCF8591; //写入器件地址
while (IICSTA != 0x18);
IICCON &= ~0x08; //清除中断标志位
IICDAT = fuc_Add; //写入地址
while (IICSTA != 0x28);
IICCON &= ~0x08; //清除中断标志位
IICDAT = fuc_Dat; //写入数据
while (IICSTA != 0x28);
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x10; //停止位发送停止信号
}
unsigned char ADC(unsigned char fuc_Add)
{
unsigned char fuc_Dat;
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x20; //起始位发送起始信号
while ((!(IICCON & 0x08)) && (IICSTA != 0x08));
IICCON &= ~0x20; //起始位停止起始信号
IICCON &= ~0x08; //清除中断标志位
IICDAT = PCF8591; //写入器件地址
while (IICSTA != 0x18);
IICCON &= ~0x08; //清除中断标志位
IICDAT = fuc_Add; //写入读地址
while (IICSTA != 0x28);
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x20; //起始位发送起始信号
while ((!(IICCON & 0x08)) && (IICSTA != 0x08));
IICCON &= ~0x20; //起始位停止起始信号
IICCON &= ~0x08; //清除中断标志位
IICDAT = PCF8591 | 0x01; //写入读指令
while (IICSTA != 0x40);
IICCON &= ~0x08; //清除中断标志位
while (IICSTA != 0x58);
fuc_Dat = IICDAT; //读入数据
IICCON &= ~0x08; //清除中断标志位
IICCON |= 0x10; //停止位发送停止信号
return fuc_Dat;
}
/***************************************************************************************
* @实现效果 UART1接收到上位机发送的数据后,把接收的数据再次发送给上位机
* @注意 波特率1200,8位数据,无校验位
***************************************************************************************/
void main(void)
{
uint8_t bai,shi,ge;
uint16_t i;
/********************************系统初始化*******************************************/
WDTCCR = 0x00; //关闭看门狗
//本例程为方便测试关闭看门狗,实际使用中,建议客户打开看门狗,详见WDT复位例程
CLKCON = 0x02; //选择内部高频RC为系统时钟,Fosc=32MHz
CLKDIV = 0x02; //Fosc 2分频得到Fper,Fper=16MHz
/**********************************IO配置初始化**************************************/
P2M2 = P2M2&0x0F|0x20; //P25设置为上拉输入
P2M2 = P2M2&0xF0|0x08; //P24设置为推挽输出
P0M0 = P0M0 & 0xF0 | 0x0A; //P00带上拉开漏输出
P0M0 = P0M0 & 0x0F | 0x80; //P01推挽输出
SCL_MAP = 0x01; //SCL映射P01口
SDA_MAP = 0x00; //SDA映射P00口
IICCON = 0x40; //启动IIC模块
/**********************************UART配置初始化**************************************/
TXD_MAP = 0x14; //TXD映射P24
RXD_MAP = 0x15; //RXD映射P25
//8位数据发送,波特率1200
//波特率计算
//波特率 = 1/16 * 时钟源频率 / (65536 - 0xFCBE)
// = 1/16 * 16000000 / 834)
// = 1199.04(误差0.05%)
//波特率1200
//反推初值
//初值 = (65536 - (Fper / 波特率) * (1 / 16))
// = (65536 - (16000000 / 1200) * (1 / 16))
// = (65536 - 833.33)
// = FCBE
SBRTH = 0xFCBE/256;
SBRTL = 0xFCBE%256;
SCON2 = 0x12; //8位UART 独立波特率,波特率可变
SCON = 0x10; //开串口接收
//IE = 0x10; //使能串口中断
//EA = 1; //使能总中断
while(1)
{
ADCVALUE=ADC(0x43); //ADC0 模数转换1 光敏电阻
bai=ADCVALUE/100+0x30;
shi=ADCVALUE%100/10+0x30;
ge=ADCVALUE%10+0x30;
txBuf[11]=bai;
txBuf[12]=shi;
txBuf[13]=ge;
for(i = 0; i < sizeof(txBuf); i++)
{
SBUF = txBuf[i]; //发送数据
while(!(SCON&0x02));
SCON &=~ 0x02; //发送中断请求中断标志位?
}
delay(2000);
// for(i=0;i<50000;i++);
}
}
/***************************************************************************************
* @说明 UART1中断服务函数
* @参数 无
* @返回值 无
* @注 无
***************************************************************************************/
void delay(volatile uint i)
{
volatile uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
效果图:
|