我使用STM8L051F3芯片作为从机,
STM32L476作为主机,但STM8L拒绝响应,它一直报告SR2-> BERR即忙碌错误。
我知道STM32代码没问题,因为我有两个代码在没有任何问题的情况下工作在I2C链接上,但是当我使用STM8作为从属时它失败了。
时钟和数据线在示波器上看起来不错,漂亮和正方形。我比较了32-32和32-8的信号,在32-8中'ACK'脉冲保持高电平而不是拉低。
STM8L代码粘贴在下面
--- I2C设置:---
void Init_I2C(void)
{
CLK-> CKDIVR = 0; // sys clock / 1
CLK-> PCKENR1 | = 0x08; //启用I2C外设clk //初始化GPIO以供I2C使用
GPIOC-> DDR | = 0x03; //输出模式
GPIOC-> CR1& = 0xFC; //带开漏的输出
GPIOC-> CR2 | = 0x03; //快// --- PE之前设定= 1 ---
I2C1-> TRISER = 2;
//设置时钟控制寄存器(CCR)
I2C1-> CCRL = 0x50; //提供100kHz的输出时钟......
I2C1-> CCRH =(u8)0; // ...占空比为50%
//如果I2C1参数未激活,则无法更改它!
I2C1-> CR1 = 0x01; //启用I2C外设
I2C1-> CR2 = 0x04; //启用I2C确认
I2C1-> FREQR = 16; //设置I2C频率值(16MHz)
I2C1-> OARL =(SLAVE_ADDRESS<< 1); //设置从站地址(将寄存器的0xA2加到7位地址)
I2C1-> OARH = 0x40; //设置7bit地址模式
I2C1-> ITR = 0x07; //所有I2C中断使能
} - - 打断 - -
@far @interrupt void I2C_Slave_check_event(void)
{
静态u8 sr1;
静态u8 sr2;
静态u8 sr3;
//保存I2C寄存器配置
sr1 = I2C1-> SR1;
sr2 = I2C1-> SR2;
sr3 = I2C1-> SR3;
//
通信故障?
if(sr2& I2C_SR2_WUFH)
{
I2C1-> CR2 | = I2C_CR2_STOP; //停止沟通 - 释放线条
I2C1-> SR2 = 0; //清除所有错误标志
}
否则如果(sr2& I2C_SR2_OVR)
{
I2C1-> CR2 | = I2C_CR2_STOP; //停止沟通 - 释放线条
I2C1-> SR2 = 0; //清除所有错误标志
}
否则如果(sr2& I2C_SR2_BERR)
{// ----总是得到这个标志----
I2C1-> CR2 | = I2C_CR2_STOP; //停止沟通 - 释放线条
I2C1-> SR2 = 0; //清除所有错误标志
}
//收到更多字节?
if((sr1&(I2C_SR1_RXNE | I2C_SR1_BTF))==(I2C_SR1_RXNE | I2C_SR1_BTF))
{
I2C_byte_received(I2C1-> DR);
}
//字节收到?
if(sr1& I2C_SR1_RXNE)
{
I2C_byte_received(I2C1-> DR);
}
// NAK? (=从发送通信结束)
if(sr2& I2C_SR2_AF)
{
I2C1-> SR2& = ~I2C_SR2_AF; //清除自动对焦
I2C_transac
tion_end();
}
//从Master停止位(=从端接收comm的结束)
if(sr1& I2C_SR1_STOPF)
{
I2C1-> CR2 | = I2C_CR2_ACK; // CR2写入清除STOPF
I2C_transaction_end();
}
//从站地址匹配(=启动Comm)
if(sr1& I2C_SR1_ADDR)
{
I2C_transaction_begin();
}
//要传输更多字节?
if((sr1&(I2C_SR1_TXE | I2C_SR1_BTF))==(I2C_SR1_TXE | I2C_SR1_BTF))
{
I2C1-> DR = I2C_byte_write();
}
//字节传输?
if(sr1& I2C_SR1_TXE)
{
I2C1-> DR = I2C_byte_write();
}
}
#stm8l051f3#i2c-busy
以上来自于谷歌翻译
以下为原文
I'm using an STM8L051F3 chip as slave and a STM32L476 as master, but the STM8L refuses to respond, it keeps reporting a SR2->BERR aka busy error.
I know the STM32 code is ok as I had two of them working on an I2C link without any problems, but when I use an STM8 as a slave it fails.
The clock and data lines look ok on a scope, nice and square. I have compared the signals from 32-32 and 32-8, in the 32-8 the 'ACK' pulse remains high instead of being pulled low.
STM8L code pasted below
--- I2C setup : ---
void Init_I2C(void)
{
CLK->CKDIVR = 0; // sys clock /1
CLK->PCKENR1 |= 0x08; // enable I2C peripheral clk// Init GPIO for I2C use
GPIOC->DDR |= 0x03; // Output mode
GPIOC->CR1 &= 0xFC; // Output with Open drain
GPIOC->CR2 |= 0x03; // Fast// --- SET BEFORE PE = 1 ---
I2C1->TRISER = 2;
// Set the clock control register (CCR)
I2C1->CCRL = 0x50; // Provides an output clock of 100kHz...
I2C1->CCRH = (u8)0; // ...at 50% duty cycle
// Cannot change I2C1 parameters if it is not active !
I2C1->CR1 = 0x01; // Enable I2C peripheral
I2C1->CR2 = 0x04; // Enable I2C acknowledgement
I2C1->FREQR = 16; // Set I2C Freq value (16MHz)
I2C1->OARL = (SLAVE_ADDRESS << 1) ; // set slave address (put 0xA2 for the register dues to7bit address)
I2C1->OARH = 0x40; // Set 7bit address mode
I2C1->ITR = 0x07; // all I2C interrupt enable
}--- Interrupt ---
@far @interrupt void I2C_Slave_check_event(void)
{
static u8 sr1;
static u8 sr2;
static u8 sr3;
// save the I2C registers configuration
sr1 = I2C1->SR1;
sr2 = I2C1->SR2;
sr3 = I2C1->SR3;
// Communication error?
if (sr2 & I2C_SR2_WUFH)
{
I2C1->CR2 |= I2C_CR2_STOP; // stop communication - release the lines
I2C1->SR2 = 0; // clear all error flags
}
else if (sr2 & I2C_SR2_OVR)
{
I2C1->CR2 |= I2C_CR2_STOP; // stop communication - release the lines
I2C1->SR2 = 0; // clear all error flags
}
else if (sr2 & I2C_SR2_BERR)
{// ---- ALWAYS GET THIS FLAG SET ----
I2C1->CR2 |= I2C_CR2_STOP; // stop communication - release the lines
I2C1->SR2 = 0; // clear all error flags
}
// More bytes received ?
if ((sr1 & (I2C_SR1_RXNE | I2C_SR1_BTF)) == (I2C_SR1_RXNE | I2C_SR1_BTF))
{
I2C_byte_received(I2C1->DR);
}
// Byte received ?
if (sr1 & I2C_SR1_RXNE)
{
I2C_byte_received(I2C1->DR);
}
// NAK? (=end of slave transmit comm)
if (sr2 & I2C_SR2_AF)
{
I2C1->SR2 &= ~I2C_SR2_AF; // clear AF
I2C_transaction_end();
}
// Stop bit from Master (= end of slave receive comm)
if (sr1 & I2C_SR1_STOPF)
{
I2C1->CR2 |= I2C_CR2_ACK; // CR2 write to clear STOPF
I2C_transaction_end();
}
// Slave address matched (= Start Comm)
if (sr1 & I2C_SR1_ADDR)
{
I2C_transaction_begin();
}
// More bytes to transmit ?
if ((sr1 & (I2C_SR1_TXE | I2C_SR1_BTF)) == (I2C_SR1_TXE | I2C_SR1_BTF))
{
I2C1->DR = I2C_byte_write();
}
// Byte to transmit ?
if (sr1 & I2C_SR1_TXE)
{
I2C1->DR = I2C_byte_write();
}
}
#stm8l051f3 #i2c-busy