我想在
STM32F401xx MCU
中使用两个proteus
。其中一个是成为 master
,另一个是成为 slave
。
这是我给大师的代码:
使用 (
MicroC Pro For Arm
) 程序。
#include <stdint.h>
#include <stdio.h>
uint8_t temp=0;
void begin(uint8_t addr);
void end(void);
void Write (uint8_t dat);
void main() {
// Enable the I2C CLOCK and GPIO CLOCK
RCC_APB1ENR |= (1<<21); // enable I2C CLOCK
RCC_AHB1ENR |= (1<<1); // Enable GPIOB CLOCK
// Configure the I2C PINs for ALternate Functions
//PB8 and PB9 are connected to I2C1_SCL and I2C1_SDA
GPIOB_MODER |= (2<<16) | (2<<18);
GPIOB_OTYPER |= (1<<8) | (1<<9);
GPIOB_OSPEEDR |= (3<<16) | (3<<18);
GPIOB_PUPDR |= (1<<16) | (1<<18);
GPIOB_AFRH |= (4<<0) | (4<<4);
begin(0x08);
Write(0x01);
end();
}
void begin(uint8_t addr){
//join I2C as a master mode
//Generate a start condition
I2C1_CR1 |= (1<<10); // Enable the ACK
I2C1_CR1 |= (1<<8); // Generate START
while (!(I2C1_SR1 & (1<<0))); // Wait for SB bit to set to 1
//Send the Slave Address to the DR Register
I2C1_DR = addr; // send the address
while (!(I2C1_SR1 & (1<<1))); //
temp = I2C1_SR1 | I2C1_SR2; // read SR1 and SR2 to clear the ADDR bit
// Reset the I2C
I2C1_CR1 |= (1<<15); //I2C Peripheral under reset state -->page.493 manual
I2C1_CR1 &= ~(1<<15); //I2C Peripheral not under reset -->page.493 manual
// Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings
I2C1_CR2 |= (42 <<0); // PCLK1 FREQUENCY in MHz
I2C1_CCR = 210<<0; // Configure the clock control registers
I2C1_TRISE = 43; // Configure the rise time register
I2C1_CR1 |= (1<<0); // Enable I2C
}
void end(void) {
I2C1_CR1 |= (1<<9);//stop generation
// Wait until the STOP condition is complete
while (I2C1_SR2 & (1<<0)); //Cleared by hardware after detecting a Stop condition on the bus
// Clear the STOP bit
I2C1_CR1 &= ~(1<<9);
}
void Write (uint8_t dat)
{
while (!(I2C1_SR1 & (1<<7))); // wait for TXE bit to set
I2C1_DR = dat ; // wait for BTF bit to set
while (!(I2C1_SR1 & (1<<2))); //waiting while BTF=0 but when BTF=1; Data byte transfer succeeded
}
从机代码:
#include <stdint.h>
#include <stdio.h>
uint8_t temp=0;
uint8_t state =0x00;
void begin(uint8_t addr);
void end(void);
uint8_t Read ();
void main() {
RCC_APB1ENR |= (1<<21); // enable I2C CLOCK -
RCC_AHB1ENR |= (1<<1); // Enable GPIOB CLOCK
RCC_AHB1ENR |= (1<<0); // Enable GPIOA CLOCK
GPIOA_MODER |=(1<<0); //set pin 0 as output
// Configure the I2C PINs for ALternate Functions
//PB8 and PB9 are connected to I2C1_SCL and I2C1_SDA
GPIOB_MODER |= (2<<16) | (2<<18);
GPIOB_OTYPER |= (1<<8) | (1<<9);
GPIOB_OSPEEDR |= (3<<16) | (3<<18);
GPIOB_PUPDR |= (1<<16) | (1<<18);
GPIOB_AFRH |= (4<<0) | (4<<4);
begin(0x08);
state = Read();
end();
if (state == 0x01){
GPIOA_ODR |=(1<<0);//set 1 for pin 0
}
}
void begin(uint8_t addr){
//join I2C bus as a slave mode
I2C1_CR2 |= (42<<0); // PCLK1 FREQUENCY in MHz
I2C1_OAR1 = addr;//own address interface
I2C1_CR1 |= (1<<0); // Enable I2C
I2C1_CR1 |= (1<<10); // Enable the ACK ,indicate that a byte is received
}
void end(void) {
I2C1_CR1 |= (1<<9);//stop generation
// Wait until the STOP condition is complete
while (I2C1_SR2 & (1<<0)); //Cleared by hardware after detecting a Stop condition on the bus
// Clear the STOP bit
I2C1_CR1 &= ~(1<<9);
}
uint8_t Read (){
uint8_t receivedData = 0;
I2C1_CR1 &= ~(1<<10); // clear the ACK bit
temp = I2C1_SR1 | I2C1_SR2; // read SR1 and SR2 to clear the ADDR bit.... EV6 condition
I2C1_CR1 |= (1<<9); // Stop I2C
while (!(I2C1_SR1 & (1<<6))); // wait for RxNE to set
receivedData = I2C1_DR; // Read the data from the DATA REGISTER
return receivedData;
}
我尝试在Proteus上进行模拟,但是没有什么可以改变的,
led still off
。所以,我想知道如何在Proteus上制作simulation
,如果我提供的代码有任何问题,我按照STM32F401xx的datasheet
和manual
来编写这个简单的驱动程序。
proteus
两个 STM32F401xx MCU 的连接:
你的主人的“开始”功能做了一些奇怪的事情。
I2C1_TRISE = 43;
after 设置起始位怎么样?您在配置之前尝试使用 I2C。在使用任何应答或起始位之前,TRISE 必须是对 I2C 执行的首要操作之一。整个函数以奇怪的顺序执行操作。
寄存器中的“起始位”不启用起始位功能。当您写入时,它实际上会尝试立即发送一个起始位,并且在您的代码中,它会在您设置 TRISE 之前甚至在启用 I2C 外设之前发生。因此,行为是不可预测的。
我检查了F401的外设,它与F103的外设一模一样,只是F401多了一个用于模拟和数字噪声滤波器控制的寄存器。除此之外,它们是相同的并且完美地映射到另一个。 (根据勘误表,F401 不存在与 F103 相同的带有滤波器故障的硅缺陷)。
以下是我使用该外设的操作顺序,跳过了明显的 GPIO 备用功能设置,因此此处仅注册 I2C。这是 I2C 主设备配置,但一般设置是相同的,从设备配置和主设备配置之间的区别在于以下必要步骤:
现在,如果您写入起始位,您可以将数据加载到 DR 并将其作为主设备发送。到目前为止,您不需要向 Start 位写入任何内容,也不需要向 ACK 位写入任何内容,这些位用于正在进行的通信,而不是用于配置。
对于从机,您可以进行类似的设置,但显然还需要配置其从机地址。
我觉得你太着急了。从主 MCU 开始,确保您首先可以在 I2C 线路上看到一些内容。