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

I2C. Передача слова конфигурации ведомому. Разрыв мозга!

30.01.2017, 11:50. Показов 4200. Ответов 34
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Уважаемые господа! Требуется коллективное сознание для "осознания".. Есть, как оказалось проблема, решение которой я, пока что не нашёл, несмотря на многочасовые "упражнения" мозга.
Начну с начальных признаков этого безобразия:
Здесь, на форуме, я как-то ещё осенью 2016г общался по поводу взаимодействия STM32 с датчиками температуры DS1621. Те проблемы с которыми я обращался были успешно решены и забыты. Была забыта и ещё одна, как на тот момент казалось "проблемка".. Но вот пришлось таки с этой "проблемкой" столкнуться вновь и понять, что это не случайность и частный случай, а закономерность, которая требует разрешения!
Итак! Всё началось с конфигурации датчика DS1621. Работает он, как известно по I2C. Для того чтобы, например, инициировать однократное преобразование температуры и установить активный уровень выхода термостата "Hi", в регистр конфигурации датчика нужно записать 0x03..
Вот тут мне пришлось покорячиться. Это значение ни под каким соусом не записывалось в регистр как 0x03 bin=(00000011) и как следствие датчик не запускался на преобразование. Не знаю что на меня нашло.. но я почему-то интуитивно решил попробовать поставить в сташий бит слова "1", в результате получилось 0х83 bin=(10000011). Регистр записался, преобразование запустилось, всё заработало. В этом регистре управляющие биты только [1:0], поэтому установка старшего бита влияет только на корректность записи в регистр. Я имел разговор по этому поводу с участником форума Rius`ом и он мне тогда указал, что возможно некорректно работает процедура передачи байта ведомому. Я "списал" эту проблему на датчик и забыл о ней.. До начала работы уже с другим датчиком. BME280. Когда я дошёл до его конфигурирования и реального запуска измерений, то всплыла вот эта "забытая" проблема. Точно такая же история с конфигурацией!!!
Для того, чтобы установить датчик в режим непрерывного измерения давления и температуры и выбрать оверсэмплинг указанных параметров х1 нужно записать в регистр ctrl_meas значение 0x27 bin=(00100111).
До этого момента всё шло как по маслу. Калибровочные параметры прочитались как положено. История в этом посте: Работа с датчиком давления BME280. Обсуждение, обмен опытом
Дошёл до получения некомпенсированных значений P; RH; T..
Хрена!! Молчит "как рыба об лёд"!!! Тупил весь вечер. Пока не вспомнил про вышеупомянутую проблему с "1" в старшем разряде. И вот, я выбираю слово конфигурации "оверсэмплинг температуры и давления х16, нормальный режим работы" значение этого слова 0xA7 bin=(10110111). Исключительный запуск, появляются измеренные значения!!!!! Опять эта злосчастная "1" в адресе 0x80
Значит проблема всё-таки не в датчиках! Что же это за "косяк" такой, хитрый?? Просмотрел в своём коде процедуру передачи байта ведомому. Вроде никакого "криминала" С этой процедурой прекрасно работает двухточечный термометр 2х DS1621. Но.. Адрес DS1621 0x90 bin=(10010000) (опять эта долбаная единица!) поэтому всё что касается адресации датчиков работает безукоризненно. А вот к конфигурации приходится добавлять эту недостающую "1", чтобы запустить измерения. Вот, собственно максимальное описание сути имеющейся проблемы. Прошу помощи!!! Может кто-либо сталкивался с такой фигнёй?? Помогите пофиксить!! Привожу код функции, отвечающей за передачу байта ведомому. Буду крайне благодарен за помощь в разрешении ситуации!!!!
****
КОД:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//***********************************<<<--Передача байта в ведомое устройство-->>>****************************************************************
void I2C_ByteTX(uint8_t TxBfr)  // Функция передачи байта в ведомое устройство
{
    uint8_t Bn;                                     // Bits number Счётчик количества передаваемых бит
    uint8_t Sn;                                     // Shifts number Счётчик количества сдвигов
    for (Bn=0; Bn<8; Bn++)              // Цикл последовательной передачи бит
{
    if (!(TxBfr&0x80))                      // Проверка "0" значения передаваемого бита 
    {I2C_SDA_L;}                                    // Очередной передаваемый бит "0". Установка линии SDA в состояние "LOW"
    if (TxBfr&0x80)                             // Проверка значения "1" передаваемого бита
    {I2C_SDA_H;}                                    // Передаваемый бит "1". Установка линии SDA в состояние "HIGH"
    I2C_SCL_H;                                      // Фронт тактового импульса SCL. Начало передачи бита данных.
    while   (!SCLSTATE){}                       // Ожидание освобождения линии SCL если она удерживается ведомым устройством
    I2C_Tmng (72, THClk);                   // Полупериод  HIGH тактового импульса SCL. Тактирование передачи бита.
    I2C_SCL_L;                                      // Спад тактового импульса SCL. Окончание передачи бита.
    I2C_Tmng (72, TLClk);                   // Полупериод  LOW тактового импульса SCL.
    if (Sn<=6)                                      // Проверка количества сдвигов буфера передаваемых данных
    {TxBfr=TxBfr<<1; Sn++;}             // Не все сдвиги выполнены. Сдвиг буфера передаваемых данных на один бит влево. Инкремент счётчика сдвигов 
}
    I2C_SDA_H;                                      // Передача байта окончена. Освобождение линии SDA.
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I2C_SDA_H; I2C_SDA_L; I2C_SCL_H; I2C_SCL_L - атомарные операции установки/сброса порта вывода
I2C_Tmng - временные задержки на таймере в однопроходном режиме
Ну и аргумент функции, естественно, передаваемый байт.
Жду с нетерпением ответа(ов) знающих
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.01.2017, 11:50
Ответы с готовыми решениями:

передача текста i2c
Доброго времени суток. Ребята, подскажите как передать текст через микроконтроллер I2C. Нужно...

Передача данных по i2c
Добрый день! Хочу передать данные по i2c (stm8) и программа зависает на while Вот ф-я передачи...

I2C slave: прием и передача
Добрый день! Понадобилось поднять I2C-slave режим на stm32, чтобы данные принимались и...

Передача массива данных по i2c
Добрый день, Уже перепробовал всё что знал и всё до чего смог додуматься. собственно сама...

34
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,659
Записей в блоге: 14
10.02.2017, 19:34 21
Author24 — интернет-сервис помощи студентам
Уровень абстракции не очень.
Эти последовательности в большинстве своём одинаковы. Нет смысла для каждого устройства перечислять старт/стоп/рестарт. Можно и ошибиться.
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
10.02.2017, 19:42  [ТС] 22
Ну хорошо, я на данный момент не совсем понимаю что вы до меня хотите донести, но если образно сказать, то как можно дать "домашнее задание ученику Васе" не обратившись к нему, не описав упражнения, которые нужно решить и не оговорив сроки выполнения этого задания, в конце диалога не сказав ему "Досвиданья, Вася" (стоп-условие)
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,659
Записей в блоге: 14
10.02.2017, 19:45 23
Очень просто: записать задание в общем формате, понятном и Васе , и Маше, и Пете, и всем их десяти братьям и сёстрам. И пусть выполняют, как принято.

Добавлено через 1 минуту
Это, конечно, не обязательно. Но после нескольких разных устройств может быть наконец надоест и тогда уже обобщите код.
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
10.02.2017, 19:48  [ТС] 24
Можно же сказать "Здравствуйте дети" (старт-условие) потом используя стандартные фразы русского языка назначить дежурных по классу, отправить "Петю" за водой для протирки доски, провести урок, обращаясь к разным детям и в конце урока сказать им "Урок окончен, все свободны" (стоп-условие).

Добавлено через 2 минуты
Вот я только что об этом написал. Это мне понятно, но пока не нужно. На этом этапе. Я когда-нибудь стану "настоящим сталеваром" вот тогда и буду "варить высоколегированную сталь"
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,659
Записей в блоге: 14
10.02.2017, 19:48 25
Сначала да. А позже приходишь к состоянию, в котором уже задолбало одно и то же описывать каждый раз...
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
10.02.2017, 19:58  [ТС] 26
Кстати, я за сегодняшний день потрудился над тем, чтобы моя I2C библиотека окончательно стала набором стандартных процедур. И таки теперь она окончательно "вылизана как у кота..." А теперь подставляя в эти процедуры что передать, в какой последовательности принять, когда сказать "здравствуйте", когда "досвиданья" я могу хоть чёртом лысым с интерфейсом I2C управлять!

Добавлено через 3 минуты
Цитата Сообщение от Rius Посмотреть сообщение
Сначала да. А позже приходишь к состоянию, в котором уже задолбало одно и то же описывать каждый раз...
Да, да, совершенно согласен. И "сталеваром" я рано или поздно буду. И тогда...
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
04.03.2017, 21:20  [ТС] 27
Может кому пригодятся мои скромные труды.. Вот окончательно "вылизанный" код библиотеки программной реализации 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
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
167
168
169
170
171
172
//***********************************************************************************************
// Библиотека программной реализации шины I2C                                                                                                    *
//***********************************************************************************************
//***********************************<<<--Подключение заголовочных файлов-->>>********************************************************************
#include "stm32f10x.h"                      // Device header
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//************************************<<<--Объявление макросов шины I2C-->>>**********************************************************************
#define SCL_H   GPIOA->BSRR |= GPIO_BSRR_BS6    // Установка PA6. Освобождение SCL.
#define SCL_L   GPIOA->BSRR |= GPIO_BSRR_BR6    // Сброс PA6. Захват SCL.
#define SDA_H   GPIOA->BSRR |= GPIO_BSRR_BS7    // Установка PA7. Освобождение SDA.
#define SDA_L   GPIOA->BSRR |= GPIO_BSRR_BR7    // Сброс PA7. Захват SDA.
#define SCLLVL  GPIOA->IDR & GPIO_IDR_IDR6  // Текущее состояние линии SCL.
#define SDALVL  GPIOA->IDR & GPIO_IDR_IDR7  // Текущее состояние линии SDA.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//********************************<<<--Служебные константы, переменные и флаги шины I2C-->>>******************************************************
const uint8_t TSC=6;        // TimeOfStartCondition. Тайминг фиксации старт/стоп условий.
const uint8_t TFBS=6;       // TimeOfFreeBusState. Тайминг фиксации свободного состояния шины.
const uint8_t TDRdy=2;  // TimeOfDataReady. Тайминг готовности данных
const uint8_t TRs=2;      // TimeOfRise. Тайминг фронта SDA и SCL.
const uint8_t TFl=5;      // TimeOfFall. Тайминг спада SDA и SCL. 
const uint8_t THClk=5;  // TimeOfHiClock. Тайминг HCLK.
const uint8_t TLClk=6;  // TimeOfLoClock. Тайминг LCLK.
uint8_t             S1AckFlg;   // Sensor1AcknowledgeFlag. Флаг бита AckS BME280 1.(Addr=0x76)
uint8_t             S2AckFlg;   // Sensor2AcknowledgeFlag. Флаг бита AckS BME280 2.(Addr=0x77)
uint8_t             RxBfr;      // ReceivedDataBuffer/ Буфер приёма байт
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*******************************<<<--Процедура формирования временных интервалов шины I2C-->>>***************************************************
//  Аргументы функции:                                                                                                                                                                                                                                                   *
//  [PSCVal] PrescalerValue. Значение предделителя таймера. Множитель длительности временного интервала.                                         *
//  [ARRVal] AutoReloadRegisterValue. Значение регистра автоперезагрузки таймера. Длительность временного интервала.                                   *
//************************************************************************************************************************************************
void I2C_Tmng(char PSCVal, char ARRVal)
{
    TIM3->CR1 |= TIM_CR1_OPM;               // Выбор режима таймера "OPM".
    TIM3->PSC = PSCVal;                             // Запись текущего значения PSC.
    TIM3->ARR = ARRVal-1;                     // Запись текущего значения ARR.
    TIM3->EGR |= TIM_EGR_UG;                    // Реинициализация счётчика. Обновление PSC и ARR.
    TIM3->CR1 |= TIM_CR1_CEN;               // Разрешение счётчика.
    while (TIM3->CR1 & TIM_CR1_CEN);    // Выход из функции по сбросу бита окончания счёта CEN.
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*********************************<<<--Процедура выдачи на шину старт-условия-->>>***************************************************************
void I2CStart()
{
    SDA_L;                      // Захват SDA. Начало Start-условия.
    I2C_Tmng (72,TSC);  // Тайминг действия Start-условия.
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*********************************<<<--Процедура выдачи на шину стоп-условия-->>>****************************************************************
void I2CStop()
{
  SDA_H;                        // Освобождение SDA. Начало стоп-условия.
    I2C_Tmng (72,TFBS); // Тайминг свободного состояния шины.
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//***********************************<<<--Процедура приёма Ack/NAck SlaveX.-->>>******************************************************************
//  Аргумены функции:                                                                                                                            * 
//  [SlvX] SlaveX. Условный номер целевого BME280# [1,2]                                                                                         *
//  [Cmd] Command. Std[0] Стандартный приём (выход с SCL[LOW]). BSR[1] Формирование [пред]старта/стопа (выход с SCL[HI]).                        *
//************************************************************************************************************************************************
void I2CAckRX(char SlvX,char Cmd)
{
    SCL_H;                          // Фронт CLK. Начало тактирования приёма Ack/NAck.
  I2C_Tmng (72,TRs);    // Тайминг фронта SCL.
  if (SlvX==1)          // Проверка адресации Slave1.
{                       // Адресован Slave1.
  if (SDALVL)                       // Проверка состояния бита Ack/Nack Slave1.
    S1AckFlg=0;                     // Состояние бита "1", сброс флага S1AckFlg.
    else                                    // Состояние бита "0".
    S1AckFlg=1;                     // Установка флага S1AckFlg.
}
  if (SlvX==2)          // Проверка адресации Slave2.
{                       // Адресован Slave2.
  if (SDALVL)                       // Проверка состояния бита Ack/Nack Slave2.
    S2AckFlg=0;                     // Состояние бита "1". Сброс флага S2AckFlg.
    else                                    // Состояние бита "0".
    S2AckFlg=1;                     // Установка флага S2AckFlg.
}                       
    I2C_Tmng (72,THClk);  // Полупериод  HCLK. Тактирование приёма Ack/NAck.
  SCL_L;                            // Спад CLK. Захват SCL. Окончание тактирования приёма Ack/NAck. 
  I2C_Tmng (72,TLClk);  // Полупериод LCLK.
//------------------------<<<--Формирование [пред]стопового/повторного старта состояния шины-->>>-------------------------------------------------
  if (Cmd)              // Проверка наличия идентификатора формирования состояния [пред]стопа/повторного старта.
{
  SCL_H;                // Освобождение SCL.
    while   (!SCLLVL){}         // Ожидание освобождения SCL если её удерживает Slave.
  I2C_Tmng (72,TSC);    // Интервал фиксации стоп-условия
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//*************************************<<<--Процедура передачи байта.-->>>************************************************************************
//  Аргумент функции: [Byte] Значение передаваемого байта                                                                                        *
//************************************************************************************************************************************************
void I2CByteTx(char Byte)
{
    uint8_t Nb;                     // NumberOfBits Счётчик передаваемых бит.
    uint8_t Ns=0;                   // NumberOfShifts Счётчик сдвигов буфера передачи.
    SCL_L;                            // Захват SCL.
  I2C_Tmng (7,TFl);     // Тайминг спада SCL.
    for (Nb=0;Nb<8;Nb++)    // Цикл передачи байта.
{
    if (Byte & 0x80)          // Проверка значения передаваемого бита адреса SlaveX.
    {SDA_H;}                          // Передаваемый бит "1". Установка SDA в "1".
    else                                  // Передаваемый бит "0".
    {SDA_L;}                          // Установка SDA в "0".
    I2C_Tmng (72,TDRdy);    // Тайминг готовности данных.
    SCL_H;                            // Фронт CLK. Начало тактирования передачи бита данных.
    I2C_Tmng (72,THClk);  // Полупериод  HCLK.
    SCL_L;                            // Спад CLK. Окончание тактирования передачи бита данных. Захват SCL.
  I2C_Tmng (72,TLClk);  // Полупериод LCLK.
  if (Ns<=6)            // Проверка количества сдвигов буфера передачи.
  {Byte<<=1;Ns++;}      // Не все сдвиги выполнены. Сдвиг буфера передачи на один бит влево. Инкремент счётчика сдвигов.          
}
  SDA_H;                              // Передача байта окончена. Освобождение линии SDA перед приёмом Ack/Nack.
  I2C_Tmng (72,TRs);    // Тайминг фронта SDA.
}
//************************************************************************************************************************************************
//****************************<<<--Процедура приёма байта из SlaveX и передачи бита AckM/NAckM-->>>***********************************************
//  Аргумент функции:    [AckCmd] Команда идентификации передачи бита AckM/NAckM. AckCmd=1: передача AckM; AckCmd=0: передача NAckM.                *
//************************************************************************************************************************************************
void I2CByteRX(char AckCmd)
{
    uint8_t Nb;                         // NumberOfBits Счётчик передаваемых бит.
    uint8_t Ns=0;                       // NumberOfShifts Счётчик сдвигов буфера приёма.
    RxBfr=0;                                // Очистка буфера приёма.
    SCL_L;                              // Захват SCL.
  I2C_Tmng (7,TFl);       // Тайминг спада SCL.
    for (Nb=0; Nb<8; Nb++)  // Цикл приёма байта.
{
    SCL_H;                              // Фронт CLK. Начало приёма бита.
  I2C_Tmng (72,TRs);      // Тайминг фронта SCL.
    if (SDALVL)                         // Проверка значения принимаемого бита.
    {RxBfr |= 0x01;}                // Принимаемый бит "1". Установка бита 0 буфера приёма.
    else                                        // Принимаемый бит "0".
    {RxBfr &= ~0x01;}               // Сброс бита 0 буфера приёма.
    I2C_Tmng (72,THClk);        // Полупериод HCLK. Тактирование приёма бита.
    SCL_L;                            // Спад CLK. Окончание приёма бита.
    I2C_Tmng (72,TLClk);    // Полупериод LCLK.
    if (Ns<=6)              // Проверка количества сдвигов буфера приёма.
  {RxBfr<<=1;Ns++;}       // Не все сдвиги выполнены. Сдвиг буфера приёма на один бит влево. Инкремент счётчика сдвигов буфера.                                
  else
{                                                   // Все сдвиги выполнены. Начало передачи AckM/NAckM
    if (AckCmd)                         // Проверка наличия команды выдачи AckM
{                         // Распознана команда выдачи AckM.
    SDA_L;                              // Значение AckCmd "1". Выдача на SDA AckM
  I2C_Tmng (7,TFl);       // Тайминг спада SDA.
    SCL_H;                              // Фронт CLK. Начало передачи бита AckM.
    I2C_Tmng (72,THClk);        // Полупериод  HCLK. Тактирование передачи AckM.
    SCL_L;                              // Спад CLK. Окончание передачи AckM.
    I2C_Tmng (72,TLClk);    // Полупериод LCLK.
    SDA_H;                              // Освобождение SDA.
  I2C_Tmng (72,TRs);      // Тайминг фронта SDA.
}                                           
  else                                      // Распознана команда выдачи NAckM.
{
    SDA_H;                              // Выдача на SDA NAckM.
  I2C_Tmng (72,TRs);      // Тайминг фронта SDA.
    SCL_H;                              // Фронт CLK. Начало передачи NAckM.
    I2C_Tmng (72,THClk);        // Полупериод  HCLK. Тактирование передачи NAckM.
    SCL_L;                              // Спад CLK. Окончание передачи NAckM.
    I2C_Tmng    (72,TLClk);     // Полупериод LCLK.
    SDA_L;                              // Захват SDA.
  I2C_Tmng (7,TFl);       // Тайминг спада SDA.
  //------------------------<<<--Формирование [пред]стопового/повторного старта состояния шины-->>>-----------------------------------------------
    SCL_H;                          // Освобождение SCL.
    while(!SCLLVL){}              // Ожидание свободного состояния SCL если её удерживает Slave.
  I2C_Tmng(72,TSC);       // Интервал фиксации стоп-условия.
}
}
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Ну и попила ж она моей крови.. Но зато работает как часы!
Абсолютно корректная работа с двумя BME280.
В процессе отладки и оптимизации были выявлены и пофиксены некоторые "косячки" и неточности. Но всё позади!!!
Фуфффф!!! Как-то вот так
1
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
05.03.2017, 06:26 28
Цитата Сообщение от scan11 Посмотреть сообщение
C
1
#define SCL_H  GPIOA->BSRR |= GPIO_BSRR_BS6 // Установка PA6. Освобождение SCL.
ошибка, которая неизвестно когда выстрелит
правильно так
C
1
#define SCL_H   GPIOA->BSRR = GPIO_BSRR_BS6
ну и в остальных случаях так же
регистры BSRR/ BRR устанавливают/ сбрасывают биты тогда когда в определенных разрядах стоит 1, операция "ИЛИ" совершенно лишняя
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
05.03.2017, 17:44  [ТС] 29
Попробуем

Добавлено через 7 часов 19 минут
ValeryS, Спасибо огромное за подсказку. Всё работает. И действительно, ведь GPIO_BSRR_BS6 и подобное имеет значение "True", а значит "1". Перепишу во всех своих проектах!
0
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
07.03.2017, 20:03  [ТС] 30
ValeryS, А вот возник вопрос, ну или ситуация.
При замене так как Вы мне посоветовали операции "ИЛИ" на знак равенства в атомарных операциях работа программы не нарушается.
А вот если я заменяю, например: TIM3->CR1 |= TIM_CR1_CEN; // Разрешение счётчика
на: TIM3->CR1 = TIM_CR1_CEN; // Разрешение счётчика
То программа "заваливается".. Ведь логически, как я понимаю в случае с регистром таймера должно происходить то же что и с регистром атомарных операций? В соответствующем бите "поднимается" "1". Почему ж тогда атомарный регистр отрабатывает как надо, а аналогичная конструкция, в случае с таймером не проходит??
Или я "подтупливаю", по незнанию чего-либо, или ???
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,659
Записей в блоге: 14
07.03.2017, 20:13 31
scan11, представьте что "атомарные" регистры аппаратно реализуют |= и &=~
Бездумно заменять |= на = в общем случае нельзя. BSRR/BRR были специально сделаны так, чтобы избежать этих лишних операций.
1
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
07.03.2017, 20:17 32
Цитата Сообщение от scan11 Посмотреть сообщение
А вот если я заменяю, например: TIM3->CR1 |= TIM_CR1_CEN; // Разрешение счётчика
на: TIM3->CR1 = TIM_CR1_CEN; // Разрешение счётчика
То программа "заваливается"..
разумеется
это разные вещи
TIM3->CR1 |= TIM_CR1_CEN;
раскладывается
на
C
1
2
3
tmp=TIM3->CR1;
tmp=tmp| TIM_CR1_CEN;
TIM3->CR1=tmp;
как видишь, это разные вещи
1
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
07.03.2017, 21:28  [ТС] 33
Rius, ValeryS, Значит, если я правильно понял из ваших ответов, в атомарных регистрах замена "|=" на"=" возможна по аппаратным причинам, а в остальных регистрах нет..
Так?
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,659
Записей в блоге: 14
07.03.2017, 21:32 34
Да. Атомарными их и называют из-за того, что указанные операции реализуются за одну команду.
1
7 / 7 / 2
Регистрация: 08.09.2015
Сообщений: 111
07.03.2017, 21:35  [ТС] 35
Rius, Усё понятно! Огромное спасибо за разъяснение. И действительно, вспоминаю, что в атомарных регистрах специально исключён механизм чтение-модификация-запись Сорри за лёгкий "тупнячок"
0
07.03.2017, 21:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.03.2017, 21:35
Помогаю со студенческими работами здесь

QLabel разрыв слова
Подскажите, как в QLabel сделать разрыв длинного слова и чтобы qlabel увеличивался в высоту? ...

STM32 передача по I2C через DMA
Доброго времени суток! Имеется &quot;синяя пилюля&quot; stm32f103c8t6 и попытки пересылать данные по I2C...

Как сделать принудительный перенос (разрыв) слова, если оно не умещается в блоке?
Т.е. когда есть длинное слово без пробелов, типа &quot;авмолтеколтпннолитинолиетниолмтншоин6тишо&quot; и блок...

QSerialPort передача настроек с файла конфигурации
Добрый день. Туплю что-то я...подскажите пожалуйста... стандартные настройки QSerialPort...

GPS модуль EB-500. Передача команды для конфигурации
нужна помощь!! подключил GPS модуль EB-500 к компу данные приходят а вот отправить на модуль...

Конвертер i2c в usb - MIKROE-1421, FTDI click USB 2.0 to I2C для ПК
Подскажите как подключить устройство с интерфейсом i2c к компьютеру. Требуется управление с...

К какой конфигурации придёт машина Тьюринга (исходя из начальной конфигурации)
Работа машины Тьюринга определяется следующей программой: {q}_{1}3\rightarrow {q}_{1}3L;...


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

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