我使用两只stm32l152发现公猪。一个配置为主设备,另一个配置为从设备。我已经在两个都启用了确认,但是当主设备发送地址时,从设备不会在9个时钟脉冲发送确认位。端口设置为备用功能4和开漏。我使用外部4.7k上拉电阻到3.3V。我已多次检查所有寄存器,但我不知道奴隶为什么不识别它的地址。
This is the output from the logic analyser
D3是主人的起始位 D4是从站上的地址匹配位 这是奴隶代码:
#define USE_STDPERIPH_DRIVER
#include "stm32l1xx.h"
#include "stm32l1xx_conf.h"
//Quick hack, approximately 1ms delay
void ms_delay(int ms)
{
while (ms> 0) {
volatile int x = 5971;
while (x> 0) {
x--;
}
ms--;
}
}
#define SCL 8
#define SDA 9
int main(void)
{
RCC->AHBENR |= (0x1 << 1);
//set port to alternate function
GPIOB->MODER &= ~((0x3 << (2 * SCL)) | (0x3 << (2 * SDA)) | (0x3 << (2 * 5)));
GPIOB->MODER |= ((0x2 << (2 * SCL)) | (0x2 << (2 * SDA)) | (0x1 << (2 * 5)));
GPIOB->OTYPER |= ((1 << SCL) | (1 << SDA)); //set output PB6 and PB7 to open drain
//set PB6 and PB7 to no pullup no pulldown
GPIOB->PUPDR &= ~((0x3 << (2 * SCL)) | (0x3 << (2 * SDA)) | (0x3 << (2 * 5)));
//set PB6 and PB7 to alternate function 4(I2C)
GPIOB->AFR[1] &= ~((0b1111 << (4 * 0)) | (0b1111 << (4 * 1)));
//set PB6 and PB7 to alternate function 4(I2C)
GPIOB->AFR[1] |= ((0b0100 << (4 * 0)) | (0b0100 << (4 * 1)));
RCC->APB1ENR |= (1 << 21);
//reset I2C
I2C1->CR1 |= (1 << 15);
ms_delay(1);
I2C1->CR1 &= ~(1 << 15);
I2C1->CR2 |= 0b001000; //peripheral clock set to 8MHz
I2C1->CR1 |= (1 << 10); //ACK enabled
I2C1->OAR1 |= (0x05 << 1); //setting primary address
I2C1->CR1 |= 1; //I2C peripheral enabled when configuration is done
for (;;) {
if ((I2C1->SR1&(1 << 1)) != 0) {
GPIOB->ODR |= (1 << 5);
}
else {
GPIOB->ODR &= ~(1 << 5);
}
}
}
这是主代码:
#define USE_STDPERIPH_DRIVER
#include "stm32l1xx.h"
#include "stm32l1xx_conf.h"
#define SCL 8
#define SDA 9
int main(void)
{
RCC->AHBENR |= (0x1 << 1);
//set port to alternate function
GPIOB->MODER &= ~((0x3 << (2 * SCL)) | (0x3 << (2 * SDA)) | (0x3 << (2 * 5)));
GPIOB->MODER |= ((0x2 << (2 * SCL)) | (0x2 << (2 * SDA)) | (0x1 << (2 * 5)));
//set output PB6 and PB7 to open drain
GPIOB->OTYPER |= ((1 << SCL) | (1 << SDA));
//set PB6 and PB7 to no pullup no pulldown
GPIOB->PUPDR &= ~((0x3 << (2 * SCL)) | (0x3 << (2 * SDA)) | (0x3 << (2 * 5)));
//set PB6 and PB7 to alternate function 4(I2C)
GPIOB->AFR[1] &= ~((0b1111 << (4 * 0)) | (0b1111 << (4 * 1)));
//set PB6 and PB7 to alternate function 4(I2C)
GPIOB->AFR[1] |= ((0b0100 << (4 * 0)) | (0b0100 << (4 * 1)));
I2C1->CR1 |= (1 << 15);
I2C1->CR1 &= ~(1 << 15);
RCC->APB1ENR |= (1 << 21);
I2C1->CR2 |= 0x08; //peripheral clock set to 8MHz
I2C1->CCR |= 0x28; //
I2C1->TRISE |= 0x09;
I2C1->CR1 |= (1 << 10); //ACK enabled
I2C1->CR1 |= 1; //I2C peripheral enabled when configuration is done
I2C1->CR1 |= (1 << 8); //generate start condition (master mode)
for (;;) {
//check start condition
if ((I2C1->SR1&(1 << 0)) != 0) {
GPIOB->ODR |= (1 << 5);
I2C1->DR = 0x0b << 0; //send slave addres
}
else {
GPIOB->ODR &= ~(1 << 5);
}
if ((I2C1->SR1&(1 << 1)) != 0) {
GPIOB->ODR |= (1 << 5);
}
else {
GPIOB->ODR &= ~(1 << 5);
}
}
}
我使用arm-none-eabi-gcc进行编译并使用stm的stsw-stm32077图书馆
答案 0 :(得分:0)
该代码的问题是,必须在使能外设后设置ack位,如果在此之前进行设置,则会自动重置ack位。