0 / 0 / 0
Регистрация: 20.11.2019
Сообщений: 17
1

STM32F051, I2C, SPl, проблема с запуском шины

24.01.2023, 23:02. Показов 344. Ответов 13
Метки нет (Все метки)

Всем привет!
Пытаюсь запустить i2c шину.
Начинаю с простого - сканера i2c.
Честно сказать, не могу найти нормального примера, с чего можно содрать.
Подскажите, чего не хватает, чтобы найти устройство в шине?
(устройство есть, сканер на хале его находит).

Это инициализация
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void LCD_i2c1_ini (void) //init func for LCD monitor though i2c bus
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); //clocking for port B switched on
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);    //clocking for i2c swithed on
    
    GPIO_InitTypeDef GPIO_Init_i2c1;                    //definition for port struct
    GPIO_Init_i2c1.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;        //
    GPIO_Init_i2c1.GPIO_Mode = GPIO_Mode_AF;               //
    GPIO_Init_i2c1.GPIO_Speed = GPIO_Speed_Level_3;       // high speed
    GPIO_Init_i2c1.GPIO_OType = GPIO_OType_PP;          // may be PP (it was OD)
    GPIO_Init_i2c1.GPIO_PuPd = GPIO_PuPd_UP;            // may be UP (it was NOPULL)
    GPIO_Init(GPIOB, &GPIO_Init_i2c1);
    
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_3);        //switched A10 to Alternative function
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_3);        //switched A11 to AF
    
    GPIO_SetBits(GPIOB, GPIO_Pin_6);
    GPIO_SetBits(GPIOB, GPIO_Pin_7);
    
    I2C_InitTypeDef I2C_InitStruct;                                             // init struct for i2c
    //I2C_InitStruct.I2C_Timing = ;
    I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Disable;
    I2C_InitStruct.I2C_DigitalFilter = 0x00;
    I2C_InitStruct.I2C_Mode = I2C_Mode_SMBusHost;
    I2C_InitStruct.I2C_OwnAddress1 = 0b0000001;
    I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C1, &I2C_InitStruct);
    I2C_Cmd(I2C1, ENABLE);                  //switch on I2C
    //I2C1->CR1 |= ;                    // on this place should be flag after sucsessful recive byte frome slave
    I2C_ITConfig(I2C1, I2C_IT_ERRI, ENABLE);                                    // interrup by error
    I2C_ITConfig(I2C1, I2C_IT_TCI, ENABLE);                             // interrup by trancsim complete
    
    NVIC_InitTypeDef NVIC_I2C1;                                                     // Init nvic struct
    NVIC_I2C1.NVIC_IRQChannel = I2C1_IRQn;
    NVIC_I2C1.NVIC_IRQChannelCmd = ENABLE;
    NVIC_I2C1.NVIC_IRQChannelPriority = 0;
    NVIC_Init(&NVIC_I2C1); 
    
}
Это тело функции сканера
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
sprintf(sendBuffer, "Starting I2C Scanning: \r\n");
    SendtoPC();
    delay_ms(50);
  for(i=1; i<128; i++)
  {
        I2C_GenerateSTART(I2C1, ENABLE);
        while(!(I2C1->CR2 & I2C_CR2_START));
        I2C_SlaveAddressConfig(I2C1, (uint16_t) i<<1);
        delay_ms(40);
        I2C_GenerateSTOP(I2C1, ENABLE);
        delay_ms(100);
        rett = I2C_GetAddressMatched(I2C1);
        //ret = (I2C1->ISR&0b1000);
        delay_ms(10);
    if (ret == 0)
            {
                sprintf(sendBuffer, " - ");
                SendtoPC();
                delay_ms(50);
      }
      else if(ret == 1)
      {
                sprintf(sendBuffer, "%u", i);
                SendtoPC();
                delay_ms(50);
      }
   }
    sprintf(sendBuffer, "Done! \r\n\r\n");
    SendtoPC();
    delay_ms(50);
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.01.2023, 23:02
Ответы с готовыми решениями:

STM32F051 Проблема с запуском ADC от Timer1 по TRGO
Не могу завести АЦП. Все работает, если ацп запускать в автозапуске, но по таймеру1 запустить не...

STM32F0 I2C SPL, первый байт...
Подскажите, почему, при указании строки: I2C_TransferHomdling(I2C1, 0x55, 0, I2C_AutoEnd_Mode,...

Библиотека для работы с LCD Motorola T191 (I2C) STM32F051
Привет. Давно обещал - выкладываю... Проверялась на STM32F042 и на STM32F0Dyscovery (именно под...

Чтение 16 бит шины I2C
Как это можно сделать в Линуксе Ubuntu? есть i2cget , но мне надо прочитать адрес регистра из 16...

Непонятная ошибка шины i2c...
y2s работает на прерываниях, но иногда происходит что то не понятное, хаотично примерно через 5-30...

13
59 / 49 / 8
Регистрация: 25.08.2011
Сообщений: 382
25.01.2023, 08:25 2
Цитата Сообщение от vick_lo Посмотреть сообщение
сканер на хале его находит
Так и используйте HAL и не мучайтесь. Чем он не подходит?
0
0 / 0 / 0
Регистрация: 20.11.2019
Сообщений: 17
25.01.2023, 08:40  [ТС] 3
Хочу более глубоко погрузиться в вопрос, поэтому хочу без хала.
0
59 / 49 / 8
Регистрация: 25.08.2011
Сообщений: 382
25.01.2023, 08:42 4
vick_lo, так можно с HAL посмотреть как инициализаруется порт и сравнить со своими настройками. Где тов регистрах видимо какой то косяк.
0
0 / 0 / 0
Регистрация: 20.11.2019
Сообщений: 17
25.01.2023, 09:09  [ТС] 5
Цитата Сообщение от Worldmaster Посмотреть сообщение
vick_lo, так можно с HAL посмотреть как инициализаруется порт и сравнить со своими настройками. Где тов регистрах видимо какой то косяк.
Честно сказать, не хватает пока навыка докопаться до регистров в хале.
Поэтому пришел за помощью сюда.
0
59 / 49 / 8
Регистрация: 25.08.2011
Сообщений: 382
25.01.2023, 09:53 6
vick_lo, ну можно тогда и харкорно, хотя в чем тут профит кроме головной боли не ясно.

i2c.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#ifndef __I2C_H__
#define __I2C_H__
 
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
 
/* I2C SPE mask */
#define I2C_CR1_PE_Set              ((uint16_t)0x0001)
#define I2C_CR1_PE_Reset            ((uint16_t)0xFFFE)
 
/* I2C START mask */
#define I2C_CR1_START_Set           ((uint16_t)0x0100)
#define I2C_CR1_START_Reset         ((uint16_t)0xFEFF)
 
/* I2C STOP mask */
#define I2C_CR1_STOP_Set            ((uint16_t)0x0200)
#define I2C_CR1_STOP_Reset          ((uint16_t)0xFDFF)
 
/* I2C ACK mask */
#define I2C_CR1_ACK_Set             ((uint16_t)0x0400)
#define I2C_CR1_ACK_Reset           ((uint16_t)0xFBFF)
 
/* I2C ENGC mask */
#define I2C_CR1_ENGC_Set            ((uint16_t)0x0040)
#define I2C_CR1_ENGC_Reset          ((uint16_t)0xFFBF)
 
/* I2C SWRST mask */
#define I2C_CR1_SWRST_Set           ((uint16_t)0x8000)
#define I2C_CR1_SWRST_Reset         ((uint16_t)0x7FFF)
 
/* I2C PEC mask */
#define I2C_CR1_PEC_Set             ((uint16_t)0x1000)
#define I2C_CR1_PEC_Reset           ((uint16_t)0xEFFF)
 
/* I2C ENPEC mask */
#define I2C_CR1_ENPEC_Set           ((uint16_t)0x0020)
#define I2C_CR1_ENPEC_Reset         ((uint16_t)0xFFDF)
 
/* I2C ENARP mask */
#define I2C_CR1_ENARP_Set           ((uint16_t)0x0010)
#define I2C_CR1_ENARP_Reset         ((uint16_t)0xFFEF)
 
/* I2C NOSTRETCH mask */
#define I2C_CR1_NOSTRETCH_Set       ((uint16_t)0x0080)
#define I2C_CR1_NOSTRETCH_Reset     ((uint16_t)0xFF7F)
 
/* I2C registers Masks */
#define I2C_CR1_CLEAR_Mask          ((uint16_t)0xFBF5)
 
/* I2C DMAEN mask */
#define I2C_CR2_DMAEN_Set           ((uint16_t)0x0800)
#define I2C_CR2_DMAEN_Reset         ((uint16_t)0xF7FF)
 
/* I2C LAST mask */
#define I2C_CR2_LAST_Set            ((uint16_t)0x1000)
#define I2C_CR2_LAST_Reset          ((uint16_t)0xEFFF)
 
/* I2C FREQ mask */
#define I2C_CR2_FREQ_Reset          ((uint16_t)0xFFC0)
 
/* I2C ADD0 mask */
#define I2C_OAR1_ADD0_Set           ((uint16_t)0x0001)
#define I2C_OAR1_ADD0_Reset         ((uint16_t)0xFFFE)
 
/* I2C ENDUAL mask */
#define I2C_OAR2_ENDUAL_Set         ((uint16_t)0x0001)
#define I2C_OAR2_ENDUAL_Reset       ((uint16_t)0xFFFE)
 
/* I2C ADD2 mask */
#define I2C_OAR2_ADD2_Reset         ((uint16_t)0xFF01)
 
/* I2C F/S mask */
#define I2C_CCR_FS_Set              ((uint16_t)0x8000)
 
/* I2C CCR mask */
#define I2C_CCR_CCR_Set             ((uint16_t)0x0FFF)
 
/* I2C FLAG mask */
#define I2C_FLAG_Mask               ((uint32_t)0x00FFFFFF)
 
/* I2C Interrupt Enable mask */
#define I2C_ITEN_Mask               ((uint32_t)0x07000000)
 
#define DS3231_I2C_ADDR (0x68<<1)
#define DS3231_CONTROL_REG ((uint8_t)0x0E)
#define DS3231_STATUS_REG ((uint8_t)0x0F)
 
#define LAST    ((uint8_t)0x01)
#define NOLAST  ((uint8_t)0x00)
 
#define enable_i2c      I2C1->CR1 |= I2C_CR1_PE_Set;    // =1, disable I2C
#define disable_i2c     I2C1->CR1 &= I2C_CR1_PE_Reset;  // disable I2C
#define stop_i2c        I2C1->CR1 |= I2C_CR1_STOP_Set;  //=0x0200, send STOP
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last);
 
#endif

реализация

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "i2c.h"
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last) {
    I2C1->CR1 |= I2C_CR1_START_Set;             //=0x0100, START
    while (!(I2C1->SR1 & I2C_FLAG_SB));         // wait SB
    (void) I2C1->SR1;
    I2C1->DR=adr;                               // send ADDR
    while (!(I2C1->SR1 & I2C_FLAG_ADDR))        // wait ADDR
    {
        if(I2C1->SR1 & I2C_IT_AF)               // if NACK
            return 1;
    }
    (void) I2C1->SR1;                           // clear ADDR
    (void) I2C1->SR2;                           // clear ADDR
    I2C1->DR=value;
    if (last == LAST) {
        while(!(I2C1->SR1 & I2C_FLAG_BTF));     // wait BFT
        I2C1->CR1 |= I2C_CR1_STOP_Set;          // Program the STOP bit
        while (I2C1->CR1 & I2C_CR1_STOP_Set);   // Wait until STOP bit is cleared by hardware
    } else {
        while(!(I2C1->SR1 & I2C_FLAG_TXE));     // wait TXE bit
    }
    return 0;
}

ну и использование как то так:

C++
1
2
3
4
5
6
7
8
9
10
11
for(adr=0;adr<128;adr++) {
            enable_i2c;
            if (init_i2c((adr<<1), 0x0, LAST) == 0) {
                usart1_print_string("Device was found: ");
                usart1_print_hex(adr);
                usart1_send_char('\n');
            } else
                stop_i2c;
            delay(20);
            disable_i2c;
        }
0
0 / 0 / 0
Регистрация: 20.11.2019
Сообщений: 17
25.01.2023, 15:40  [ТС] 7
Цитата Сообщение от Worldmaster Посмотреть сообщение
vick_lo, ну можно тогда и харкорно, хотя в чем тут профит кроме головной боли не ясно.

i2c.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#ifndef __I2C_H__
#define __I2C_H__
 
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
 
/* I2C SPE mask */
#define I2C_CR1_PE_Set              ((uint16_t)0x0001)
#define I2C_CR1_PE_Reset            ((uint16_t)0xFFFE)
 
/* I2C START mask */
#define I2C_CR1_START_Set           ((uint16_t)0x0100)
#define I2C_CR1_START_Reset         ((uint16_t)0xFEFF)
 
/* I2C STOP mask */
#define I2C_CR1_STOP_Set            ((uint16_t)0x0200)
#define I2C_CR1_STOP_Reset          ((uint16_t)0xFDFF)
 
/* I2C ACK mask */
#define I2C_CR1_ACK_Set             ((uint16_t)0x0400)
#define I2C_CR1_ACK_Reset           ((uint16_t)0xFBFF)
 
/* I2C ENGC mask */
#define I2C_CR1_ENGC_Set            ((uint16_t)0x0040)
#define I2C_CR1_ENGC_Reset          ((uint16_t)0xFFBF)
 
/* I2C SWRST mask */
#define I2C_CR1_SWRST_Set           ((uint16_t)0x8000)
#define I2C_CR1_SWRST_Reset         ((uint16_t)0x7FFF)
 
/* I2C PEC mask */
#define I2C_CR1_PEC_Set             ((uint16_t)0x1000)
#define I2C_CR1_PEC_Reset           ((uint16_t)0xEFFF)
 
/* I2C ENPEC mask */
#define I2C_CR1_ENPEC_Set           ((uint16_t)0x0020)
#define I2C_CR1_ENPEC_Reset         ((uint16_t)0xFFDF)
 
/* I2C ENARP mask */
#define I2C_CR1_ENARP_Set           ((uint16_t)0x0010)
#define I2C_CR1_ENARP_Reset         ((uint16_t)0xFFEF)
 
/* I2C NOSTRETCH mask */
#define I2C_CR1_NOSTRETCH_Set       ((uint16_t)0x0080)
#define I2C_CR1_NOSTRETCH_Reset     ((uint16_t)0xFF7F)
 
/* I2C registers Masks */
#define I2C_CR1_CLEAR_Mask          ((uint16_t)0xFBF5)
 
/* I2C DMAEN mask */
#define I2C_CR2_DMAEN_Set           ((uint16_t)0x0800)
#define I2C_CR2_DMAEN_Reset         ((uint16_t)0xF7FF)
 
/* I2C LAST mask */
#define I2C_CR2_LAST_Set            ((uint16_t)0x1000)
#define I2C_CR2_LAST_Reset          ((uint16_t)0xEFFF)
 
/* I2C FREQ mask */
#define I2C_CR2_FREQ_Reset          ((uint16_t)0xFFC0)
 
/* I2C ADD0 mask */
#define I2C_OAR1_ADD0_Set           ((uint16_t)0x0001)
#define I2C_OAR1_ADD0_Reset         ((uint16_t)0xFFFE)
 
/* I2C ENDUAL mask */
#define I2C_OAR2_ENDUAL_Set         ((uint16_t)0x0001)
#define I2C_OAR2_ENDUAL_Reset       ((uint16_t)0xFFFE)
 
/* I2C ADD2 mask */
#define I2C_OAR2_ADD2_Reset         ((uint16_t)0xFF01)
 
/* I2C F/S mask */
#define I2C_CCR_FS_Set              ((uint16_t)0x8000)
 
/* I2C CCR mask */
#define I2C_CCR_CCR_Set             ((uint16_t)0x0FFF)
 
/* I2C FLAG mask */
#define I2C_FLAG_Mask               ((uint32_t)0x00FFFFFF)
 
/* I2C Interrupt Enable mask */
#define I2C_ITEN_Mask               ((uint32_t)0x07000000)
 
#define DS3231_I2C_ADDR (0x68<<1)
#define DS3231_CONTROL_REG ((uint8_t)0x0E)
#define DS3231_STATUS_REG ((uint8_t)0x0F)
 
#define LAST    ((uint8_t)0x01)
#define NOLAST  ((uint8_t)0x00)
 
#define enable_i2c      I2C1->CR1 |= I2C_CR1_PE_Set;    // =1, disable I2C
#define disable_i2c     I2C1->CR1 &= I2C_CR1_PE_Reset;  // disable I2C
#define stop_i2c        I2C1->CR1 |= I2C_CR1_STOP_Set;  //=0x0200, send STOP
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last);
 
#endif

реализация

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "i2c.h"
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last) {
    I2C1->CR1 |= I2C_CR1_START_Set;             //=0x0100, START
    while (!(I2C1->SR1 & I2C_FLAG_SB));         // wait SB
    (void) I2C1->SR1;
    I2C1->DR=adr;                               // send ADDR
    while (!(I2C1->SR1 & I2C_FLAG_ADDR))        // wait ADDR
    {
        if(I2C1->SR1 & I2C_IT_AF)               // if NACK
            return 1;
    }
    (void) I2C1->SR1;                           // clear ADDR
    (void) I2C1->SR2;                           // clear ADDR
    I2C1->DR=value;
    if (last == LAST) {
        while(!(I2C1->SR1 & I2C_FLAG_BTF));     // wait BFT
        I2C1->CR1 |= I2C_CR1_STOP_Set;          // Program the STOP bit
        while (I2C1->CR1 & I2C_CR1_STOP_Set);   // Wait until STOP bit is cleared by hardware
    } else {
        while(!(I2C1->SR1 & I2C_FLAG_TXE));     // wait TXE bit
    }
    return 0;
}

ну и использование как то так:

C++
1
2
3
4
5
6
7
8
9
10
11
for(adr=0;adr<128;adr++) {
            enable_i2c;
            if (init_i2c((adr<<1), 0x0, LAST) == 0) {
                usart1_print_string("Device was found: ");
                usart1_print_hex(adr);
                usart1_send_char('\n');
            } else
                stop_i2c;
            delay(20);
            disable_i2c;
        }
Во-первых, спасибо!
Во-вторых, у меня stm32fo51.
И я тут теряюсь, потому что у меня в регистре статусов нет бита старта....что можно вместо него использовать?
Может, бит BUSY?
STM32F051, I2C, SPl, проблема с запуском шины
0
59 / 49 / 8
Регистрация: 25.08.2011
Сообщений: 382
25.01.2023, 15:59 8
Цитата Сообщение от vick_lo Посмотреть сообщение
Во-вторых, у меня stm32fo51.
ну а вот так если?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stm32f0xx.h>
 
void initI2C()
{
    // Enable I2C clock
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
 
    // Configure I2C pins
    // SCL: PB6, SDA: PB7
    // Set alternate function mode
    GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);
    // Set alternate function 4 (I2C)
    GPIOB->AFR[0] |= (4 << (6 * 4)) | (4 << (7 * 4));
    // Set open-drain output type
    GPIOB->OTYPER |= (GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);
    // Set high speed
    GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7);
    // Set pull-up resistors
    GPIOB->PUPDR |= (GPIO_PUPDR_PUPDR6_0 | GPIO_PUPDR_PUPDR7_0);
 
    // Configure I2C peripheral
    // Set clock speed (100kHz)
    I2C1->TIMINGR = 0x0020020A;
    // Enable I2C
    I2C1->CR1 |= I2C_CR1_PE;
}
или как то так с отправкой байта.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stm32f0xx.h>
 
int main()
{
    // Enable the clock for the I2C peripheral
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
 
    // Configure the I2C peripheral
    I2C1->CR1 = 0;
    I2C1->CR2 = I2C_CR2_START | I2C_CR2_AUTOEND;
    I2C1->TIMINGR = 0x10504000; // Configure timing, refer to datasheet for specific values
 
    // Send start condition and device address
    I2C1->CR2 |= I2C_CR2_START;
    while(!(I2C1->ISR & I2C_ISR_TXIS));
    I2C1->TXDR = (0x50 << 1); // 0x50 is the device address, left-shifted by 1 for the R/W bit
 
    // Send data byte
    while(!(I2C1->ISR & I2C_ISR_TXIS));
    I2C1->TXDR = 0x01; // 0x01 is the data byte to be sent
 
    // Wait for the transmission to complete
    while(!(I2C1->ISR & I2C_ISR_STOPF));
 
    // Clear the STOPF flag
    I2C1->ICR = I2C_ICR_STOPCF;
}

Либо попробуйте объединить эти два примера в то что нужно вам.
0
0 / 0 / 0
Регистрация: 20.11.2019
Сообщений: 17
25.01.2023, 17:15  [ТС] 9
Цитата Сообщение от Worldmaster Посмотреть сообщение
vick_lo, ну можно тогда и харкорно, хотя в чем тут профит кроме головной боли не ясно.

i2c.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#ifndef __I2C_H__
#define __I2C_H__
 
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
 
/* I2C SPE mask */
#define I2C_CR1_PE_Set              ((uint16_t)0x0001)
#define I2C_CR1_PE_Reset            ((uint16_t)0xFFFE)
 
/* I2C START mask */
#define I2C_CR1_START_Set           ((uint16_t)0x0100)
#define I2C_CR1_START_Reset         ((uint16_t)0xFEFF)
 
/* I2C STOP mask */
#define I2C_CR1_STOP_Set            ((uint16_t)0x0200)
#define I2C_CR1_STOP_Reset          ((uint16_t)0xFDFF)
 
/* I2C ACK mask */
#define I2C_CR1_ACK_Set             ((uint16_t)0x0400)
#define I2C_CR1_ACK_Reset           ((uint16_t)0xFBFF)
 
/* I2C ENGC mask */
#define I2C_CR1_ENGC_Set            ((uint16_t)0x0040)
#define I2C_CR1_ENGC_Reset          ((uint16_t)0xFFBF)
 
/* I2C SWRST mask */
#define I2C_CR1_SWRST_Set           ((uint16_t)0x8000)
#define I2C_CR1_SWRST_Reset         ((uint16_t)0x7FFF)
 
/* I2C PEC mask */
#define I2C_CR1_PEC_Set             ((uint16_t)0x1000)
#define I2C_CR1_PEC_Reset           ((uint16_t)0xEFFF)
 
/* I2C ENPEC mask */
#define I2C_CR1_ENPEC_Set           ((uint16_t)0x0020)
#define I2C_CR1_ENPEC_Reset         ((uint16_t)0xFFDF)
 
/* I2C ENARP mask */
#define I2C_CR1_ENARP_Set           ((uint16_t)0x0010)
#define I2C_CR1_ENARP_Reset         ((uint16_t)0xFFEF)
 
/* I2C NOSTRETCH mask */
#define I2C_CR1_NOSTRETCH_Set       ((uint16_t)0x0080)
#define I2C_CR1_NOSTRETCH_Reset     ((uint16_t)0xFF7F)
 
/* I2C registers Masks */
#define I2C_CR1_CLEAR_Mask          ((uint16_t)0xFBF5)
 
/* I2C DMAEN mask */
#define I2C_CR2_DMAEN_Set           ((uint16_t)0x0800)
#define I2C_CR2_DMAEN_Reset         ((uint16_t)0xF7FF)
 
/* I2C LAST mask */
#define I2C_CR2_LAST_Set            ((uint16_t)0x1000)
#define I2C_CR2_LAST_Reset          ((uint16_t)0xEFFF)
 
/* I2C FREQ mask */
#define I2C_CR2_FREQ_Reset          ((uint16_t)0xFFC0)
 
/* I2C ADD0 mask */
#define I2C_OAR1_ADD0_Set           ((uint16_t)0x0001)
#define I2C_OAR1_ADD0_Reset         ((uint16_t)0xFFFE)
 
/* I2C ENDUAL mask */
#define I2C_OAR2_ENDUAL_Set         ((uint16_t)0x0001)
#define I2C_OAR2_ENDUAL_Reset       ((uint16_t)0xFFFE)
 
/* I2C ADD2 mask */
#define I2C_OAR2_ADD2_Reset         ((uint16_t)0xFF01)
 
/* I2C F/S mask */
#define I2C_CCR_FS_Set              ((uint16_t)0x8000)
 
/* I2C CCR mask */
#define I2C_CCR_CCR_Set             ((uint16_t)0x0FFF)
 
/* I2C FLAG mask */
#define I2C_FLAG_Mask               ((uint32_t)0x00FFFFFF)
 
/* I2C Interrupt Enable mask */
#define I2C_ITEN_Mask               ((uint32_t)0x07000000)
 
#define DS3231_I2C_ADDR (0x68<<1)
#define DS3231_CONTROL_REG ((uint8_t)0x0E)
#define DS3231_STATUS_REG ((uint8_t)0x0F)
 
#define LAST    ((uint8_t)0x01)
#define NOLAST  ((uint8_t)0x00)
 
#define enable_i2c      I2C1->CR1 |= I2C_CR1_PE_Set;    // =1, disable I2C
#define disable_i2c     I2C1->CR1 &= I2C_CR1_PE_Reset;  // disable I2C
#define stop_i2c        I2C1->CR1 |= I2C_CR1_STOP_Set;  //=0x0200, send STOP
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last);
 
#endif

реализация

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "i2c.h"
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last) {
    I2C1->CR1 |= I2C_CR1_START_Set;             //=0x0100, START
    while (!(I2C1->SR1 & I2C_FLAG_SB));         // wait SB
    (void) I2C1->SR1;
    I2C1->DR=adr;                               // send ADDR
    while (!(I2C1->SR1 & I2C_FLAG_ADDR))        // wait ADDR
    {
        if(I2C1->SR1 & I2C_IT_AF)               // if NACK
            return 1;
    }
    (void) I2C1->SR1;                           // clear ADDR
    (void) I2C1->SR2;                           // clear ADDR
    I2C1->DR=value;
    if (last == LAST) {
        while(!(I2C1->SR1 & I2C_FLAG_BTF));     // wait BFT
        I2C1->CR1 |= I2C_CR1_STOP_Set;          // Program the STOP bit
        while (I2C1->CR1 & I2C_CR1_STOP_Set);   // Wait until STOP bit is cleared by hardware
    } else {
        while(!(I2C1->SR1 & I2C_FLAG_TXE));     // wait TXE bit
    }
    return 0;
}

ну и использование как то так:

C++
1
2
3
4
5
6
7
8
9
10
11
for(adr=0;adr<128;adr++) {
            enable_i2c;
            if (init_i2c((adr<<1), 0x0, LAST) == 0) {
                usart1_print_string("Device was found: ");
                usart1_print_hex(adr);
                usart1_send_char('\n');
            } else
                stop_i2c;
            delay(20);
            disable_i2c;
        }
Сделал вот так. Застрял в первом цикле while

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "I2C.h"
 
 
uint8_t init_i2c(uint8_t adr, uint8_t value, uint8_t last, uint8_t *isError)
{
    uint16_t i=0;
    *isError = 0;
    I2C1->CR2 |= 0b10000000000000; //start i2c
    while ((!(I2C1->ISR & 0b10))|!(*isError & 0b1)) // whait start bit. ????
    {
        i++;
        if (i>WHILE_MAX_CYCLE) 
        {
            i=0;
            *isError |= 0b1;
        }
    }
    (void) I2C1->ISR;   //????
    I2C1->TXDR=adr;
    while (((!(I2C1->ISR & 0b1000)))|!(*isError & 0b10))        //wait ADDR
    {
        if (I2C1->ISR & 0b10000)            //if NACKF
            return 1;
        i++;
        if (i>WHILE_MAX_CYCLE) 
        {
            i=0;
            *isError |= 0b10;
        }
    }
    (void) I2C1->TXDR; //clear ADDR
    I2C1->TXDR=value;
    if (last == LAST) {
        while ((!(I2C1->ISR & 0b1000000))|!(*isError & 0b100))              // wait Transmission Complete
        {
            i++;
            if (i>WHILE_MAX_CYCLE) 
            {
                i=0;
                *isError |= 0b100;
            }
        }
        stop_i2c;                                                               // Programm the STOP bit
        while ((!(I2C1->CR2 & 100000000000000))|!(*isError & 0b1000))   // Wait until STOP bit is cleared by hardware
        {
            i++;
            if (i>WHILE_MAX_CYCLE) 
            {
                i=0;
                *isError |= 0b1000;
            }
        }
    } else {
        while ((!(I2C1->ISR & 0b1))|!(*isError & 0b10000))                          // Wait TXE bit
        {
            i++;
            if (i>WHILE_MAX_CYCLE) 
            {
                i=0;
                *isError |= 0b10000;
            }
        }
    }
    return 0;
}
0
205 / 143 / 27
Регистрация: 14.02.2013
Сообщений: 1,086
25.01.2023, 20:01 10
Цитата Сообщение от Worldmaster Посмотреть сообщение
Так и используйте HAL и не мучайтесь. Чем он не подходит?
Тем что нельзя переходить по вектору прерывания когда пришёл один байт в приёмник SPI.
0
Модератор
Эксперт по электронике
8759 / 6549 / 887
Регистрация: 14.02.2011
Сообщений: 22,971
25.01.2023, 20:24 11
Цитата Сообщение от VladimirU Посмотреть сообщение
Тем что нельзя переходить по вектору прерывания когда пришёл один байт в приёмник SPI.
настройки покажи и SPI и прерывания
0
0 / 0 / 0
Регистрация: 20.11.2019
Сообщений: 17
25.01.2023, 22:28  [ТС] 12
Уважаемые, может сначала поможете мне запустить I2C, а потом про прерывания?

Добавлено через 2 часа 0 минут
С помощью ЛА понял, что у меня была нулевая активность на пинах шины из-за неверно выбранного режима альтернативной функции.
Может кто-нибудь объяснить, почему одной альтернативной функции соответствую несколько дефайнов?
C
1
2
3
4
5
6
7
8
9
10
11
12
#define GPIO_AF_1            ((uint8_t)0x01) /* USART2, CEC, TIM3, USART1, IR,
                                                EVENTOUT, I2C1, I2C2, TIM15, SPI2,
                                                USART3, TS, SPI1 */
/** 
  * @brief  AF 2 selection
  */
#define GPIO_AF_2            ((uint8_t)0x02) /* TIM2, TIM1, EVENTOUT, TIM16, TIM17,
                                                USB */
/** 
  * @brief  AF 3 selection
  */
#define GPIO_AF_3            ((uint8_t)0x03) /* TS, I2C1, TIM15, EVENTOUT */
0
59 / 49 / 8
Регистрация: 25.08.2011
Сообщений: 382
26.01.2023, 09:13 13
Цитата Сообщение от VladimirU Посмотреть сообщение
Тем что нельзя переходить по вектору прерывания когда пришёл один байт в приёмник SPI.
С какого это перепуга??

А это для кого сделано?
C++
1
2
3
4
void HAL_I2C_MasterRxCpltCallback (I2C_HandleTypeDef * hi2c)
{
  // RX Done .. Do Something!
}

vick_lo, вам все таки стоит генерировать проект в HAL и там уже смотреть какую инициализацию проводит он. Мне кажется это будет продуктивнее.

вот на вскидку выдрал кусок оттуда конфигурации
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* I2C1 clock enable */
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);
 
/* Disable the selected I2C peripheral */
(CLEAR_BIT(I2C1->CR1, I2C_CR1_PE))
 
/* Configure I2Cx: Frequency range */
I2C1->TIMINGR =  0x2000090E & TIMING_CLEAR_MASK;
 
/* Disable Own Address1 before set the Own Address1 configuration */
I2C1->OAR1 &= ~I2C_OAR1_OA1EN;
 
/* Configure I2Cx: Own Address1 I2C_ADDRESSINGMODE_7BIT */
I2C1->OAR1 = (I2C_OAR1_OA1EN | 0);
 
/* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
I2C1->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
 
/* Disable Own Address2 before set the Own Address2 configuration */
I2C1->OAR2 &= ~I2C_DUALADDRESS_ENABLE;
 
/* Configure I2Cx: Dual mode and Own Address2 */
I2C1->OAR2 = (I2C_DUALADDRESS_DISABLE | 0 | (I2C_OA2_NOMASK << 8));
 
/* Configure I2Cx: Generalcall and NoStretch mode */
I2C1->CR1 = (I2C_GENERALCALL_DISABLE | I2C_NOSTRETCH_DISABLE);
 
/* Enable the selected I2C peripheral */
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);

проверка на шине

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#define I2C_GET_FLAG(ptr, flag) (((((ptr)->ISR) & (flag)) == (flag)) ? SET : RESET)
#define I2C_CLEAR_FLAG(ptr, flag) (((flag) == I2C_FLAG_TXE) ? ((ptr)->ISR |= (flag)) : ((ptr)->ICR = (flag)))
#define I2C_GENERATE_START(__ADDMODE__,__ADDRESS__) (((__ADDMODE__) == I2C_ADDRESSINGMODE_7BIT) ? \
                                                     (uint32_t)((((uint32_t)(__ADDRESS__) & (I2C_CR2_SADD)) | \
                                                                 (I2C_CR2_START) | (I2C_CR2_AUTOEND)) & \
                                                                (~I2C_CR2_RD_WRN)) : \
                                                     (uint32_t)((((uint32_t)(__ADDRESS__) & (I2C_CR2_SADD)) | \
                                                                 (I2C_CR2_ADD10) | (I2C_CR2_START)) & \
                                                                (~I2C_CR2_RD_WRN)))
 
 
bool IsReady()
{
if(I2C_GET_FLAG(I2C1, I2C_FLAG_BUSY))
{
    return false;
}
 
/* Generate Start */
I2C1->CR2 = I2C_GENERATE_START(I2C_ADDRESSINGMODE_7BIT, DevAddress);
 
tmp1 = I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
tmp2 = I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
 
if((tmp1 == RESET) && (tmp2 == RESET))
{
    return false;
}
 
 
/* Check if the NACKF flag has not been set */
if (I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET)
{
    /* Wait until STOPF flag is reset */
    if (I2C_WaitOnFlagUntilTimeout(I2C_FLAG_STOPF, RESET, Timeout) != HAL_OK)
    {
      return false;
    }
 
    /* Clear STOP Flag */
    I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
 
    /* Device is ready */
    return true;
}
else
{
    /* Wait until STOPF flag is reset */
    if (I2C_WaitOnFlagUntilTimeout(I2C_FLAG_STOPF, RESET, Timeout) != HAL_OK)
    {
      return false;
    }
 
    /* Clear NACK Flag */
    I2C_CLEAR_FLAG(I2C1, I2C_FLAG_AF);
 
    /* Clear STOP Flag, auto generated with autoend*/
    I2C_CLEAR_FLAG(I2C1, I2C_FLAG_STOPF);
}
}
и таймер ожидания упрощенный

C++
1
2
3
4
5
6
7
8
9
10
11
12
static bool I2C_WaitOnFlagUntilTimeout(uint32_t Flag, FlagStatus Status, uint32_t Timeout )
{
  while (I2C_GET_FLAG(I2C1, Flag) == Status)
  {
    /* Check for the Timeout */
    if (!Timeout--)
    {
      return false;
    }
  }
  return true;
}
0
205 / 143 / 27
Регистрация: 14.02.2013
Сообщений: 1,086
26.01.2023, 19:55 14
Цитата Сообщение от Worldmaster Посмотреть сообщение
А это для кого сделано?
C
1
2
3
void HAL_I2C_MasterRxCpltCallback (I2C_HandleTypeDef * hi2c)
{
  // RX Done .. Do Something!
}
Попробуй используй.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.01.2023, 19:55
Помогаю со студенческими работами здесь

Высокоскоростной режим I2C-шины
Есть контроллер STM32F103C8T6, на котором поддерживаются только медленные I2C-режимы в 100 кГц и...

После чтения теряет арбитраж шины I2C (STM32F100RB)
Перенёс с stm32f407 на stm32f100rb проектик с I2C, после чтения регистра линия SDA падает в 0 и там...

Проблемы с работой LCD1602A через контроллер шины I2C PCF8574T
Здравствуйте. Пишу код на C для работы с дисплеем LCD1602A через PCF8574T по аппаратному I2C...

Назначение и основные характеристики системной шины. Шины ISA, EISA, VLB, PCI, AGP
Ребят требуеться помощь с ответом на вопрос: Назначение и основные характеристики системной шины....

Знатокам шины CAN. Как программно можно сбросить счетчики ошибок шины CAN по приему и передаче?
Дело в том, что в нормальном режиме, когда можно и передавать в шину CAN сообщения и принимать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru