簡體   English   中英

stm32l152作為I2C從設備未確認地址

[英]stm32l152 as I2C slave not acknowledging address

我正在使用兩只stm32l152發現野豬。 一個配置為主機,另一個配置為從機。 我對兩個都啟用了確認,但是當主機發送地址時,從機不會在9個時鍾脈沖時發送ack位。 端口設置為備用功能4並開漏。 我正在使用外部4.7k上拉電阻至3.3V。 我已經多次檢查了所有寄存器,但不知道為什么從機無法識別其地址。

這是邏輯分析儀的輸出

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庫

該代碼的問題在於,必須在使能外設后設置ack位,如果在此之前進行了設置,則ack位會自動重置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM