Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 26.11.2019
Сообщений: 31
1

Не генерируется стартовый бит I2C STM32F100RBT6B (STM32 Discovery)

29.03.2024, 13:18. Показов 528. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте!
Пытался прошить EDID (EEPROM память 24АА16), используя I2C на отладочной плате STM32 Discovery (MB913C). Изначально всё работало, но через некоторое время плата перестала отсылать стартовый бит. Зависает на моменте "while(~I2C1->SR1&(1<<0)){};", т.е. проверки генерации стартового бита. В коде в функции инициализации первая половина - из ERRATA по чипу STM32F100RBT6.

Вообще, плата странно себя ведёт. Работаю в кейле, делаю Build, потом Load (F7, потом F8), всё работало, но теперь перестало) Были моменты, когда в режиме отладки, проходя код по шагам, я проходил момент зависающей проверки и прошивал память, но теперь и этого не происходит. Вообще не уверен, что проблема с кодом, но пока думаю только в этом направлении.
Сейчас даже в режиме отладки не могу пройти зависающую проверку. Пробовал на нескольких отладочных платах - результат аналогичный.

Кто-то сталкивался с таким? Как лечили? Может быть всё-таки какая-то критическая ошибка в коде, которую я в упор не вижу?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.03.2024, 13:18
Ответы с готовыми решениями:

I2C на stm32-discovery непонятная проблема
Возникла проблема: при попытке связать датчик LSM303DLH(акселерометр+нигнитометр в одном корпусе) с...

Не генерируется стартовый бит I2C STM32F100RBT6B (STM32 Discovery)
Здравствуйте! Пытался прошить EDID (EEPROM память 24АА16), используя I2C на отладочной плате STM32...

STM32F100RB (discovery) и I2C
Приветствую всех, и прошу помочь советом: не могу добиться взаимности от y2s на обозначенной...

STMF051R8 Discovery, STM32F0Snippet и I2C
Может сюда вопрос, а может и в детские надо... Есть платка Дискавери с STM32F051R8, есть либа...

Проблемы с I2C - STM8S Discovery
Не могу понять, как запустить I2C на STM8S - Dyscovery. I2C поднимаю впринципе впервые. Компилятор...

11
3219 / 2362 / 540
Регистрация: 11.09.2009
Сообщений: 8,605
29.03.2024, 14:35 2
Цитата Сообщение от adobson Посмотреть сообщение
Пробовал на нескольких отладочных платах - результат аналогичный.
Уточните. То есть любая другая плата тоже сначала работает, а через некоторое время перестаёт, или любая новая плата теперь сразу не работает? При таком разном "поведении" плат будут явно разные причины.
0
0 / 0 / 0
Регистрация: 26.11.2019
Сообщений: 31
29.03.2024, 14:44  [ТС] 3
Цитата Сообщение от i8085 Посмотреть сообщение
или любая новая плата теперь сразу не работает
Все платы теперь не работают. Думаю, может какая-то настройка в кейле слетела или была мной неосознанно изменена.

Добавлено через 2 минуты
Странно, тем создал две, в этой нет кода. Подскажите, кстати, куда писать, чтобы удалили повторяющуюся?)
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <stm32f10x.h> 
#include <stdio.h>
 
 
#define EEPROM_INIT_ADDRESS 0xA0
#define EEPROM_REQUEST_WRITE 0x00
#define EEPROM_REQUEST_READ 0x01
 
static uint8_t a = 16;
static uint8_t c=0;
 
int MASTER, BUSY;
MASTER = 0;
BUSY = 0;
 
uint8_t WRITE_ARR_EDID[128] =
{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 
    0x12, 0xE5, 0x00, 0x21, 0x50, 0x2D, 0x31, 0x01, 
    0x1C, 0x13, 0x01, 0x03, 0x81, 0x2F, 0x1A, 0x78, 
    0x2E, 0x35, 0x85, 0xA6, 0x56, 0x48, 0x9A, 0x24, 
    0x12, 0x50, 0x54, 0x00, 0x08, 0x00, 0x01, 0x01, 
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0x19, 
    0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88, 
    0x36, 0x00, 0xDC, 0x2E, 0x11, 0x00, 0x00, 0x18, 
    0x00, 0x00, 0x00, 0xFF, 0x00, 0x30, 0x0A, 0x0A, 
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 
    0x0A, 0x0A, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x38, 
    0x4B, 0x1E, 0x53, 0x15, 0x00, 0x0A, 0x20, 0x20, 
    0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 
    0x00, 0x56, 0x47, 0x41, 0x0A, 0x0A, 0x0A, 0x0A, 
    0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0xFF};
 
void GPIO_INIT(void);
void I2C_1_INIT(void);
 
void I2C_1_WRITE_BITE (uint16_t ADDRESS, uint8_t *BUFFER, uint16_t COUNTER);
 
int main(void)
{
    //GPIO_INIT();
    I2C_1_INIT();
    
    MASTER = 0;
    BUSY = 0;
    
    while(c<a)
        {
            I2C_1_WRITE_BITE(0x0000+0x0008*c, WRITE_ARR_EDID, 0+c*8);
            c++;
            /*uint16_t CZ=0;
            while (CZ<10000) CZ++;*/
        }
}
 
void GPIO_INIT(void)
    {
        /* PB6 - SCL, PB7 - SDA*/
        
        GPIOB->CRL &= (0xFF)<<24; //Set 0 PB6 and PB7 bits
        GPIOB->CRL |= 0xFF<<24; //Set PB6 and PB7 bits as 1011
        
        RCC->APB2ENR |= 0x1<<3; //IOPB clock enable
        RCC->APB2ENR |= 0x01<<0; //AFIO clock enable
    }
 
void I2C_1_INIT(void)
    {
        ///I2C init from errata
        I2C1->CR1 &= ~(0x01<<0); //Peripherial disable - just to set I2C safety
        
        RCC->APB2ENR |= 0x1<<3; 
        GPIOB->CRL &= (0xFF)<<24; 
        GPIOB->CRL |= 0x77<<24; 
        GPIOB->ODR |= 0x3<<6; //Set PB6 and PB67 as GP output open-drain, HIGH LEVEL
        
        while(~GPIOB->IDR&(0x3<<6)){} //Check SCL and SDA high level
            
        GPIOB->ODR &=   ~(0x01<<7); //RESET SDA
            
        while(GPIOB->IDR&(0x01<<7)){} //Check SDA is 0
 
        GPIOB->ODR &=   ~(0x01<<6); //RESET SCL
            
        while(GPIOB->IDR&(0x01<<6)){}   //Check SCL is 0
            
        GPIOB->ODR |=   (0x01<<6); //SET SCL
            
        while(~GPIOB->IDR&(0x01<<6)){} //Check SCL is 1     
            
        GPIOB->ODR |=   (0x01<<7); //SET SDA
            
        while(~GPIOB->IDR&(0x01<<7)){} //check SDA is 1
        
        //RCC->APB2ENR |= 0x01<<0; //AFIO clock enable
        GPIOB->CRL &= (0xFF)<<24; 
        GPIOB->CRL |= 0xFF<<24;
            
        I2C1->CR1 |= 0x01<<15; //Set SWRST bit as 1
            
        I2C1->CR1 &= ~(0x01<<15); //Reset SWRST bit
        
        I2C1->CR1 |= (0x01<<0);
        
        ////
        RCC->APB1ENR |= 0x01<<21; //I2C_1 clock enable
        
        I2C1->OAR2 &= ~(0x01<<0); // Double address disable
        I2C1->CR1 &= ~(0x01<<6); //General call disable
        I2C1->CR1 &= ~(0x01<<7); //Clock stretching enable - задержанный отклик, если SLSAVE не может откликнуться мгновенно
        
        I2C1->CR1 &= ~(0x01<<0); //Peripherial disable - just to set I2C safety
 
        I2C1->CR2 |= 0x08; //FREQ for I2C periph = 8MHz
        I2C1->CCR &= ~(0x01<<15|0x01<<14); // Standart mode, ?t_low/t_high = 2? - not sure if it's work on standart mode
        I2C1->CCR |= 0x28; // 0x28 = 40, T_high = CCR*T_PCLK1 = 40*(1/8000000) = 1/100kHz
        
        I2C1->OAR1 = 0x4000;
        
        I2C1->CR1 &= ~(0x01<<1|0x01<<3|0x01<<4);
        
        I2C1->CR1 &= ~(0x01<<10); 
        I2C1->CR1 |= 0x01<<10; //Reset and set Acknowledge enable bit
        
        I2C1->OAR2 &= ~(0xFF);//Reset 0-7 bits
        
        I2C1->CR1 |= 0x01<<0; //Peripherial enable
        
        if (~I2C1->SR2&(0x01<<0)) MASTER=1;
        if (~I2C1->SR2&(0x01<<1)) BUSY=1;
    }
    
void I2C_1_WRITE_BITE (uint16_t ADDRESS, uint8_t *BUFFER, uint16_t COUNTER)
    {
        uint16_t i=0+8*c;
    
    I2C1->CR1&=~(1<<11); //Diasble POS bit in CR1
    I2C1->CR1|=(1<<10); //ACK=1 - acknowledge enable
    I2C1->CR1|=(1<<8); //START=1 - generating start condition
    while(~I2C1->SR1&(1<<0)){}; //Wait for SB bit in SR1 is ready - strat condition generated
    (void) I2C1->SR1;
    I2C1->DR=EEPROM_INIT_ADDRESS|EEPROM_REQUEST_WRITE;
    while(~I2C1->SR1&(1<<1)){} //Wait for ADDR = 1
    uint8_t temp = I2C1->SR1|I2C1->SR2; //Read SR1 and SR2 to clear the ADDR bit
    (void) temp;
    I2C1->DR=(ADDRESS); // Send address (MSB) - 8 bites
    while(~I2C1->SR1&(1<<7)){}//Wait for TxE=1 - Data register empty
    /*I2C1->DR=(ADDRESS); // Send address (MBS - 2nd 8 bites)
    while(~I2C1->SR1&(1<<7)){}//Wait for TxE=1 - Data register empty*/
        
        while(i<COUNTER+8)
        {
            I2C1->DR=WRITE_ARR_EDID[i];
            while(~I2C1->SR1&(1<<7)){}
            i++;
            if (i>127) break;
        }
    /*  
    for(i=0+32*c;i<COUNTER;i++)
    {
        I2C1->DR=WRITE_ARR_EDID[i];
        while(~I2C1->SR1&(1<<7)){}
    }*/
    
    I2C1->CR1|=(1<<9); //STOP=1 - generating stop condition
    }
0
3219 / 2362 / 540
Регистрация: 11.09.2009
Сообщений: 8,605
29.03.2024, 17:40 4
Цитата Сообщение от adobson Посмотреть сообщение
куда писать, чтобы удалили повторяющуюся?
Слева от сообщения, под вашим ником есть треугольник с восклицательным знаком. Нажимаете на него и пишете модератору что надо. В той теме, которую удалить просите.

Цитата Сообщение от adobson Посмотреть сообщение
какая-то настройка в кейле ... была мной неосознанно изменена.
Наиболее вероятно. Или в коде что "поправили".
Вы предыдущие версии сохраняете?
0
524 / 218 / 28
Регистрация: 22.09.2023
Сообщений: 580
29.03.2024, 23:35 5
В GPIO_INIT() как вам удается писать в GPIOB до того, как вы включили его тактирование?

Запись не проходит, нога остается в режиме входа, старт наружу выйти не может.

Цитата Сообщение от adobson Посмотреть сообщение
Думаю, может какая-то настройка в кейле слетела
Ага, "А оно само!"
0
0 / 0 / 0
Регистрация: 26.11.2019
Сообщений: 31
01.04.2024, 14:01  [ТС] 6
Цитата Сообщение от i8085 Посмотреть сообщение
Вы предыдущие версии сохраняете?
Да, но они не отличаются функционалом. Максимум - порядок изменён или какие-то настройки закомменчены.

Цитата Сообщение от Dushevny Посмотреть сообщение
В GPIO_INIT()
Если не видите - подскажу. Эта функция не используется.
0
3219 / 2362 / 540
Регистрация: 11.09.2009
Сообщений: 8,605
02.04.2024, 05:11 7
Цитата Сообщение от adobson Посмотреть сообщение
Да, но они не отличаются функционалом.
Я не про то. Попробуйте найти какую-нибудь самую старую версию, в которой точно работало, проверьте с ней. Если заработает - останется только найти разницу.
1
Нарушитель
500 / 657 / 86
Регистрация: 23.11.2021
Сообщений: 3,655
Записей в блоге: 6
02.04.2024, 08:02 8
Из-за обилия "волшебных чисел" ваш код совершенно нечитаем. Приводите в порядок, чтобы можно было сравнить с работающим.
А еще лучше - открывайте даташит и строго по порядку. У вас даже инициализация неправильная...
0
0 / 0 / 0
Регистрация: 26.11.2019
Сообщений: 31
02.04.2024, 09:44  [ТС] 9
Цитата Сообщение от Eddy_Em Посмотреть сообщение
У вас даже инициализация неправильная...
Скажите хоть, что "неправильно"?
0
Нарушитель
500 / 657 / 86
Регистрация: 23.11.2021
Сообщений: 3,655
Записей в блоге: 6
02.04.2024, 11:31 10
Вот, скажем это:
Цитата Сообщение от adobson Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
while(~GPIOB->IDR&(0x3<<6)){} //Check SCL and SDA high level
GPIOB->ODR &= ~(0x01<<7); //RESET SDA
while(GPIOB->IDR&(0x01<<7)){} //Check SDA is 0
GPIOB->ODR &= ~(0x01<<6); //RESET SCL
while(GPIOB->IDR&(0x01<<6)){} //Check SCL is 0
GPIOB->ODR |= (0x01<<6); //SET SCL
while(~GPIOB->IDR&(0x01<<6)){} //Check SCL is 1 
GPIOB->ODR |= (0x01<<7); //SET SDA
while(~GPIOB->IDR&(0x01<<7)){} //check SDA is 1
полная чушь и вообще не по даташиту!
Исправьте, чтобы не было magick numbers, тогда и вам понятно будет, и нам.
Как пример. Вот так просто I2C включается:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * PB10/PB6 - I2C_SCL, PB11/PB7 - I2C_SDA or remap @ PB8 & PB9
 */
void i2c_setup(){
    I2C1->CR1 = 0;
    I2C1->SR1 = 0;
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    GPIOB->CRL = (GPIOB->CRL & ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7)) |
            CRL(6, CNF_AFOD | MODE_NORMAL) | CRL(7, CNF_AFOD | MODE_NORMAL);
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    I2C1->CR2 = 8; // FREQR=8MHz, T=125ns
    I2C1->TRISE = 9; // (9-1)*125 = 1mks
    I2C1->CCR = 40; // normal mode, 8MHz/2/40 = 100kHz
    I2C1->CR1 |= I2C_CR1_PE; // enable periph
}
И да, я повстречал уже достаточно устройств, которые любят "класть шину". Помогает только отключение/включение их питания. Поэтому во многих своих железках (особенно если на шине несколько устройств висит) питание устройств делаю управляемым. Если хватит 0.5А, удобно использовать драйвер питания USB (там и обратная связь по КЗ есть, и сам отключит в случае необходимости).

Добавлено через 2 минуты
Но да, в сотой серии I2C - просто ад какой-то. Немногие выдерживают: большинство софтовым ногодрыгом эмулирует.
1
0 / 0 / 0
Регистрация: 26.11.2019
Сообщений: 31
02.04.2024, 12:01  [ТС] 11
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Вот, скажем это:
Это из эрраты, буквально парой строк выше написано же.

А за дальнейшее спасибо! Приму к сведению.

Пока, видимо, оставлю попытки разобраться с проблемой, потому что нашел старый, полностью рабочий в прошлом проект,- он тоже не работает)
Пока всё свалю на
Цитата Сообщение от Eddy_Em Посмотреть сообщение
в сотой серии I2C - просто ад какой-то
Всем спасибо за попытку!
0
Нарушитель
500 / 657 / 86
Регистрация: 23.11.2021
Сообщений: 3,655
Записей в блоге: 6
02.04.2024, 13:34 12
Цитата Сообщение от adobson Посмотреть сообщение
Это из эрраты
А, возможно: сотая серия еще старше 103 - там и не такое можно встретить, наверное. Я-то ориентировался по документации на 103, с 100 никогда не работал (и не собираюсь, мне геморроя со 103 хватает за глаза).
Самые удачные из слабых серий - F072 (там даже работает софтовый переход в DFU, в отличие от 042). Из помощней мне нравятся F303. Еще валяются дома и другие, но в тех же G070 практически ничего нового по сравнению с F030 (кроме, разве что, более удачного DMA, где, заняв один канал, не лишаешься доступа к куче периферии, т.к. она на нем же сидит); а в G431 USB OTG - учитывая то, что на обычный USB у меня полгода ушло, с OTG тоже могу долго провозиться, так что и не берусь пока.
0
02.04.2024, 13:34
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.04.2024, 13:34
Помогаю со студенческими работами здесь

STM32F4 Discovery I2C нет ACK
Здравствуйте. Подключаю к STM32 термодатчик по I2C. Датчик не отвечает ACK. Он как бы пытается,...

STM32F4 discovery не срабатывают прерывания по I2C
Работая по шине y2s в режиме ожидания флагов контроллер получает данные. Решил сделать работу на...

Stm32 discovery
Господа IT, решил изучить STM. почитал немного про порты и что надо тактировать.. не ужели так...

10 бит по I2C
Как по шине I2С передать 10 битное значение. До этого приходилось только 1 байтовые значения...

Выбор STM32-DISCOVERY
Всем привет. Хочу заказать плату для начинающих с STM32. Остановил свой выбор на 1)...

Утонул с Stm32 f4 discovery
купил сию платку, воткнул в windows 7 x64, а он ее не видит, соотвественно и keil тоже ее не видит....


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru