/********** STM8S硬件I2C相关操作 **********/
//初始化函数
/***********************************************************
函数名: I2C_Init()
功 能: STM8S103 MCU硬件I2C初始化
(注: 主模式,两线连接,7位地址模式,10Kbps通信速率)
参 数: 无
返回值: 无
***********************************************************/
void I2C_Init(void)
{
I2C_CR1 &= 0xFE; //PE=0,禁用硬件I2C模块(所有位置0)
CLK_PCKENR1 |= 0x01; //使能I2C时钟
I2C_CR2 |= 0x80; //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
I2C_CR2 &= 0x7F; //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
I2C_FREQR = 0x02; //配置I2C外设时钟2MHz
I2C_CCRH = 0x00; //配置I2C为标准模式及速率
I2C_CCRL = 0x64; //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
I2C_TRISER = 0x03; //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
I2C_CR1 |= 0x01; //启动I2C硬件模块
}
/***********************************************************
函数名: MCP4725_Write()/SCL-PB4,SDA-PB5/器件地址:0xC0写指令,0xC1读指令
功 能: STM8S103 MCU通过硬件I2C通信向从设备MCP4725写入器件地址、数据
参 数: data_buff --- 欲写入的多字节数据指针
data_len --- 欲写入的多字节数据长度
返回值: 无
***********************************************************/
void MCP4725_Write(uchar *data_buff,uchar data_len)
{
uchar temp; //定义一下,读取MCU状态寄存器用
uchar i; //定义一下,供循环使用
uint time; //定义一下,供等待延时用
//以下程序为I2C通信防锁死操作,非常重要!
if((PB_IDR&0x20) == 0x00) //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
{
I2C_CR1 &= 0xFE; //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
PB_DDR |= 0x10; //设置SCL端口为输出
PB_CR1 |= 0x10; //上拉输出
for(i=0;i<9;i++) //SCL端口发出9个时钟脉冲,让从设备MCP4725释放总线(恢复SDA=1)
{
PB_ODR &= (~0x10); //SCL=0;
delay_us(50); //延时(I2C通信频率10KHz)
PB_ODR |= 0x10; //SCL=1
delay_us(50); //延时(I2C通信频率10KHz)
}
time = 500; //变量赋值,准备延迟等待500次
while(!(PB_IDR&0x20)) //等待数据线SDA=1
{
if(!--time) //变量自减
return; //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
}
PB_DDR &= (~0x10); //SCL端口恢复输入方式
PB_CR1 &= (~0x10); //浮空输入
PB_ODR &= (~0x10); //清零输出寄存器
I2C_CR1 |= 0x01; //重新启动硬件I2C模块,接管SCL、SDA端口
return; //退出函数,放弃本次数据写操作
}
//以上程序为I2C通信防锁死操作,非常重要!
//以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
if((I2C_SR3&0x02) == 0x02) //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
{
I2C_CR2 |= 0x80; //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
I2C_CR2 &= 0x7F; //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
I2C_FREQR = 0x02; //配置I2C外设时钟2MHz
I2C_CCRH = 0x00; //配置I2C为标准模式及速率
I2C_CCRL = 0x64; //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
I2C_TRISER = 0x03; //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
I2C_CR1 |= 0x01; //启动I2C硬件模块
return; //退出函数,放弃本次数据写操作
}
//以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
I2C_CR2 &= 0xFB; //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
time = 500; //变量赋值,准备延迟等待500次
while(I2C_SR3&0x02) //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
{
if(!--time) //变量自减
return; //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
}
I2C_CR2 |= 0x01; //发起始条件(置位I2C_CR2控制寄存器START位)
time = 500; //变量赋值,准备延迟等待500次
while(!(I2C_SR1&0x01)) //I2C_SR1状态寄存器SB位=1表示发送成功
{
if(!--time) //变量自减
return; //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
}
delay_us(5); //短暂延时
temp = I2C_SR1; //读取状态寄存器I2C_SR1值
I2C_DR = 0xC0; //发送MCP4725从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=0表示写操作)
time = 500; //变量赋值,准备延迟等待500次
while(!(I2C_SR1&0x02)) //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
{
if(!--time) //变量自减
return; //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
}
delay_us(5); //短暂延时
temp = I2C_SR1; //读取状态寄存器I2C_SR1数值
temp = I2C_SR3; //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
while(data_len) //循环写入多字节数据
{
I2C_DR = *data_buff; //发送一字节数据
while(!(I2C_SR1&0x84)); //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
data_buff++; //准备写入下一字节数据
data_len--;
}
I2C_CR2 |= 0x02; //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
}
/***********************************************************
函数名: Voltage_Write()
功 能: STM8S103通过硬件I2C通信向 12位DAC芯片MCP4725写入输出电压数据
参 数: 无
返回值: 无
***********************************************************/
void Voltage_Write(void)
{
uint i; //定义一下,临时使用数据
i = Light_Brightness*40.96; //计算当前亮度对应12位DAC值
MCP4725_Data[0] = (i&0x0F00)>>8;//快速模式,不关断,获取电压DAC值高4位
MCP4725_Data[1] = i&0x00FF; //获取电压DAC值低8位
MCP4725_Write(MCP4725_Data,2);//写入12位电压DAC数值
}
@21小跑堂 :还有这要求啊 好吧
感谢参与原创奖励活动,此篇文章因字数未达到800字(此项为硬性指标,代码不计入字数统计)所以暂未通过审核。选题很不错,可以试试丰富完善下哦!