STC8H8K64U——I2C(PCF8591 中断方式)

i2c.h

#ifndef I2C_H
#define I2C_H

#include <STC8H.H>

sbit SCL = P3^2;
sbit SDA = P3^3;

static bit I2C_Flage; 
/*P_SW2*/
#define EAXFR    0x80; //XFR寄存器使能
#define I2C_S    0x30; //I2C功能引脚切换,SCL:P3.2,SDA:P3.3 

/*I2C配置寄存器 I2CCFG*/
#define	ENI2C    0x80  //I2C功能控制位;1:允许I2C功能,0:禁止I2C功能
#define MSSL     0x40  //I2C工作模式选择位;1:主机模式,0:从机模式
#define MSSPEED  0x3C  //I2C总线速度(等待时钟数)控制,范围0~63(0x3F),I2C总线速度 = F_OSC/2/(x*2+4) 

/*I2C主机控制寄存器 I2CMSCR*/
#define EMSI     0x80  //主机模式中断使能控制位;1:允许主机模式的中断,0:关闭主机模式的中断

//unsigned char MSCMD = 0x00;  /主机命令,0x00时,待机,无动作

#define I2C_START         0x01  //起始命令
#define I2C_SEND_DATA     0x02  //发送数据命令
#define I2C_RECEVIVE_ACK  0x03  //接收 ACK 命令
#define I2C_RECEVIVE_DATA 0x04  //接收数据命令
#define I2C_SEND_ACK      0x05  //发送 ACK 命令
#define I2C_STOP          0x06  //停止信号

#define I2C_START_DATA_ACK    0x09  //起始命令,发送数据命令,接收ACK命令依次执行。
#define I2C_SEND_DATA_ACK     0x0A  //发送数据命令,接收 ACK 命令依次执行。
#define I2C_RECEVIVE_DATA_ACK 0x0B  //接收数据命令,发送 ACK 命令依次执行。
#define I2C_RECEVIVE_DATA_NAK 0x0C  //接收数据命令,发送 NAK 命令依次执行。

/*I2C主机辅助控制寄存器 I2CMSAUX*/
#define WDTA    0x01   //主机模式I2C数据自动发送允许位,1:使能自动发送,0:禁止自动发送

/*I2C主机状态寄存器 I2CMSST*/
#define MSBUSY  0x80  //主机模式I2C控制状态位(只读位)1:忙碌状态,0:空闲状态
//(发送完START信号后,控制器会进入忙碌状态,一直持续到成功发送STOP停止信号)
#define MSIF    0x40  //主机模式中断标志位。
#define MSACKI  0x02  //主机模式接收应答位。(只读位)
#define MSACKO  0x01  //主机模式发送应答位。

void I2C_Init(void);   
void I2C_Start(void);                 //起始信号
void I2C_Stop(void);                  //终止信号
void I2C_ACK_S(bit A);	              //发送应答信号	
void I2C_ACK_R(void);	              //接收应答信号	
void I2C_SendByte(unsigned char dt);  //发送数据
unsigned char I2C_ReceiveByte(void);  //接收数据

#endif

i2c.c

#include "i2c.h"

void I2C_Init(void)            //I2C初始化
{
	P_SW2 |= EAXFR;              //XFR寄存器使能
	P_SW2 |= I2C_S;              //I2C引脚
	I2CCFG = ENI2C|MSSL|MSSPEED; //允许I2C功能,主机模式
	I2CMSST = 0x00;   	
}	

void I2C_Start(void)           //起始信号
{
	I2C_Flage = 1;
	I2CMSCR = EMSI|I2C_START;    //起始命令
	while(I2C_Flage);            //等待MSCMD命令执行完毕
}

void I2C_Stop(void)            //终止信号
{
	I2C_Flage = 1;
	I2CMSCR = EMSI|I2C_STOP;     //停止命令
	while(I2C_Flage);            //等待MSCMD命令执行完毕	
}

void I2C_ACK_R(void)	               //接收应答信号	
{
	I2C_Flage = 1;
	I2CMSCR = EMSI|I2C_RECEVIVE_ACK ;  //接收 ACK 命令
	while(I2C_Flage);                  //等待MSCMD命令执行完毕	
}

void I2C_ACK_S(bit A)	               //发送应答信号
{
/*
	发送"0101"命令到I2CMSCR寄存器的MSCMD位后,
	控制器会自动读取I2CMSST的MSACKO位的数据当作ACK数据发送到SDA。
 */
	if(A == 1)
		I2CMSST |= MSACKO;               //非应答信号
	else
		I2CMSST &= ~MSACKO; 		         //应答信号
	I2C_Flage = 1;
	I2CMSCR = EMSI|I2C_SEND_ACK ;      //发送 ACK 命令
	while(I2C_Flage);                  //等待MSCMD命令执行完毕	
}	

void I2C_SendByte(unsigned char dt)  //发送数据
{
	I2CTXD = dt;                       //写数据到数据缓冲区
	I2C_Flage = 1;
	I2CMSCR =  EMSI|I2C_SEND_DATA;     //发送数据命令
	while(I2C_Flage);                  //等待MSCMD命令执行完毕	
}

unsigned char I2C_ReceiveByte(void)  //接收数据
{
	I2C_Flage = 1;
	I2CMSCR = EMSI|I2C_RECEVIVE_DATA;  //接收数据命令
	while(I2C_Flage);                  //等待MSCMD命令执行完毕
	return I2CRXD;
}


void I2C_Isr(void) interrupt 24
{
	/*主机模式的I2C控制器执行完I2CMSCR寄存器中MSCMD命令后,
	会产生中断信号,硬件自动将MSIF位置一,向CPU发出中断请求,
	响应中断后, MSIF位必须软件清零*/	
	if(I2CMSST & MSIF)
	{
		I2CMSST &= ~MSIF;  //中断标志位清零	
		I2C_Flage = 0;		
	}
}

main.c

#include "i2c.h"
#include "led_segment.h"

//unsigned char temp[4] = {0};

/*控制字 CONTROL_BYTE*/

/*通道号,CHANNEL_NUMBER */
#define CH0 0x00
#define CH1 0x01
#define CH2 0x02
#define CH3 0x03
/*自动增益*/
#define AUTO_INCREMENT 0x04;

/*模拟输入控制
四单端输入:0x00    
三差分输入(AIN3为负):0x10 
两单端输入(AIN0,AIN1)一差分输入:0x20  ;
两差分输入(AIN1,AIN3为负):0x30*/
#define ANALOGUE_INPUT 0x00

/*模拟输出使能*/
#define ANALOGUE_OUTPUT_ENABLE 0x40

//仅模拟输出,D/A转换
void PCF8591_DAC(unsigned char addr,unsigned char value)
{	
	I2C_Start();         //起始信号	 
	I2C_SendByte(addr);  //发送地址,写
	I2C_ACK_R();         //接收应答
	
	I2C_SendByte(ANALOGUE_OUTPUT_ENABLE); //发送控制字
	I2C_ACK_R();         //接收应答
	
	I2C_SendByte(value); //发送数据
	I2C_ACK_R();         //接收应答		

	I2C_Stop();          //终止信号	
}

//仅单通道读取,A/D转换
unsigned char PCF8591_ADCS(unsigned char addr,unsigned char CONTROL_BYTE)
{

	unsigned char temp;	
	
	I2C_Start();                //起始信号	 
	I2C_SendByte(addr);         //发送地址,写
	I2C_ACK_R();                //接收应答
	I2C_SendByte(CONTROL_BYTE); //发送控制字,四单端输入
	I2C_ACK_R();                //接收应答

	I2C_Start();              //起始信号	 
	I2C_SendByte(addr|0x01);  //发送地址,读
	I2C_ACK_R();              //接收应答
	I2C_ReceiveByte();        //接收空数据
	I2C_ACK_S(0);             //发送应答			
	temp = I2C_ReceiveByte(); //接收数据
	I2C_ACK_S(1);             //发送非应答						
	I2C_Stop();               //终止信号		
	return temp;	
}
void main (void)
{
	unsigned char temp;
	unsigned int V;
	P3M0 = 0x00;
	P3M1 = 0x00;
	
	EA = 1;	
	I2C_Init();  
	SEG_GPIO_Init();

	while(1)
	{
		temp = PCF8591_ADCS(0x90,0x03);
		PCF8591_DAC(0x90,temp);
		V = temp*1.953125; // 5/256*100
		LED_7SEG_CAT_Display(V,2); 		
	}
}

/*
连续读取四个数据,A/D转换
若仅单端输入,则依次读取四个通道数据

void PCF8591_ADC(unsigned char addr,unsigned char CONTROL_BYTE,unsigned char temp[])
{	
	I2C_Start();                  //起始信号	 
	I2C_SendByte(addr);           //发送地址,写
	I2C_ACK_R();                  //接收应答
	I2C_SendByte(AUTO_INCREMENT|CONTROL_BYTE);//发送控制字,自动增益
	I2C_ACK_R();                  //接收应答
	
	I2C_Start();                  //起始信号	 
	I2C_SendByte(addr|0x01);      //发送地址,读
	I2C_ACK_R();                  //接收应答

	I2C_ReceiveByte();            //接收空数据
	I2C_ACK_S(0);                 //发送应答	
	
	temp[0] = I2C_ReceiveByte();  //接收数据
	I2C_ACK_S(0);                 //发送应答			
	temp[1] = I2C_ReceiveByte();  //接收数据
	I2C_ACK_S(0);                 //发送应答			
	temp[2] = I2C_ReceiveByte();  //接收数据
	I2C_ACK_S(0);                 //发送应答				
	temp[3] = I2C_ReceiveByte();  //接收数据
	I2C_ACK_S(1);                 //发送非应答						
	I2C_Stop();                   //终止信号		
}
*/

实物图

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STC8H8K64U-45I-TSSOP20是一款STC8系列的芯片型号。根据引用\[1\]中提到的STC8系列的内部资源表,我们可以了解到STC8H8K64U具有丰富的内部资源。同时,根据引用\[2\]中提到的LCD1602的控制命令表,我们可以了解到LCD的读写操作方式。此外,引用\[3\]中提到STC8系列芯片的输出模式,其中STC8H8K64U-45I-TSSOP20属于推挽输出模式。 #### 引用[.reference_title] - *1* [STC8H8K64U单片机学习-0-宏晶STC官网初探](https://blog.csdn.net/qq_41735476/article/details/122291519)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STC8H8K64U——LCD1602](https://blog.csdn.net/w541541/article/details/127623787)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [『STC8H8K64U』概述](https://blog.csdn.net/LYX_2937/article/details/128153591)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往昔的恒纳兰那

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值