Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
-26 / 4 / 0
Регистрация: 26.09.2024
Сообщений: 128

Передача данных по i2c через DMA STM32F401CUE6

08.10.2025, 13:46. Показов 4112. Ответов 95
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. При попытки передать данные на устройство по i2c через DMA нифига не выходит, DMA не в какую не хочет работать.

Адрес устройства определяется как надо, условие Старт и отправка адреса тоже происходит нормально но DMA не стартует и нет прерывания от DMA.
В отладке видно что бит DMA1_Stream6->CR |= DMA_SxCR_EN; устанавливается.
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
I2C_HandleTypeDef hi2c1;
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
void DMA_Init(void);
uint8_t st7567a_IsDeviceReady(I2C_HandleTypeDef i2c);
void DMA_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pBuffer, uint8_t size);
void I2C_write(I2C_HandleTypeDef *hi2c, uint8_t Addr, uint8_t *pBuffer, uint16_t size);
//==============================================================================================================================
 
uint8_t addr_i2c;
uint8_t Buffer[10] = {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xFF};
//==============================================================================================================================
 
void DMA_Init(void)
{
  __enable_irq ();
  RCC->AHB1ENR|=RCC_AHB1ENR_DMA1EN;
  DMA1_Stream6->CR = 0 ;
  DMA1_Stream6->CR |= DMA_CHANNEL_6;
  DMA1_Stream6->CR |= DMA_SxCR_MINC;
  DMA1_Stream6->CR |= DMA_SxCR_DIR_0;
  DMA1_Stream6->CR |= DMA_SxCR_TCIE | DMA_SxCR_HTIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE;
  HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
}
//==============================================================================================================================
 
uint8_t st7567a_IsDeviceReady(I2C_HandleTypeDef i2c)
{
    for(uint8_t i = 0; i < 255; i++)
    {
        HAL_Delay(10);
        if(HAL_I2C_IsDeviceReady(&i2c, i, 3, 100) == HAL_OK)
        {
            return i;
        }
    }
    return 0;
}
//==============================================================================================================================
 
void DMA1_Stream6_IRQHandler(void)
{
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    if(DMA1->HISR & DMA_HISR_TCIF6)
    {
        DMA1->HIFCR &= ~ DMA_HIFCR_CTCIF6;
        DMA1_Stream6->CR&=~DMA_SxCR_EN;
        uint8_t temp __attribute__((unused)) = hi2c1.Instance->SR1 | hi2c1.Instance->SR2;
        hi2c1.Instance->CR1 |= I2C_CR1_STOP;
        while( !( hi2c1.Instance->CR1 & I2C_CR1_STOP )) ;
    }
    else if(DMA1->HISR & DMA_HISR_HTIF6)
        {
        DMA1->HIFCR &= ~ DMA_HIFCR_CHTIF6;
        }
    else if(DMA1->HISR & DMA_HISR_TEIF6)
            {
        DMA1->HIFCR &= ~ DMA_HIFCR_CTEIF6;
            }
    else if(DMA1->HISR & DMA_HISR_DMEIF6)
            {
        DMA1->HIFCR &= ~ DMA_HIFCR_CDMEIF6;
            }
}
 
//==============================================================================================================================
uint8_t tmp = 1;
void DMA_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pBuffer, uint8_t size)
{
    DMA1_Stream6->M0AR = (uint32_t)pBuffer;
    DMA1_Stream6->PAR=(uint32_t)&hi2c->Instance->DR;
    DMA1_Stream6->NDTR = size;
    hi2c->Instance->CR2 |= I2C_CR2_DMAEN;
    DMA1_Stream6->CR |= DMA_SxCR_EN;
    tmp = 2;
}
//==============================================================================================================================
 
void I2C_write(I2C_HandleTypeDef *hi2c, uint8_t Addr, uint8_t *pBuffer, uint16_t size)
{
    while(hi2c->Instance->SR2&I2C_SR2_BUSY){;}
    hi2c->Instance->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
    while( !( hi2c->Instance->SR1 & I2C_SR1_SB )){;}
    hi2c->Instance->DR = Addr;
    while( !( hi2c->Instance->SR1 & I2C_SR1_ADDR )){;}
    DMA_Transmit(hi2c, pBuffer, size);
}
 
int main(void)
{
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
DMA_Init();
addr_i2c = st7567a_IsDeviceReady(hi2c1);
I2C_write(&hi2c1, addr_i2c, Buffer, 10);
while (1)
{
}
}
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 15;
  RCC_OscInitStruct.PLL.PLLN = 72;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_I2C1_Init(void)
{
 
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7
                          |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
                          |GPIO_PIN_12|GPIO_PIN_15, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
                          |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
                          |GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET);
 
  /*Configure GPIO pins : PC13 PC14 PC15 */
  GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
  /*Configure GPIO pins : PA0 PA1 PA2 PA3
                           PA4 PA5 PA6 PA7
                           PA8 PA9 PA10 PA11
                           PA12 PA15 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7
                          |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
                          |GPIO_PIN_12|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /*Configure GPIO pins : PB0 PB1 PB2 PB10
                           PB12 PB13 PB14 PB15
                           PB3 PB4 PB8 PB9 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
                          |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
                          |GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
  /*Configure GPIO pin : PB5 */
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
}
void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}
Добавлено через 55 минут
Нашёл ошибку DMA1_Stream6->CR |= DMA_CHANNEL_6; исправил на DMA1_Stream6->CR |= DMA_CHANNEL_1; как в таблице всё равно не хочет заводиться.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.10.2025, 13:46
Ответы с готовыми решениями:

ADC->DMA->SDIO (или NAND через FSMC) без остановки в обработчике прерываний DMA на STM32F407VG, реально или нет?
Добрый день. Столкнулся с необходимостью писать большой объём данных АЦП с высокой скоростью....

USART2(RX+IDLE+DMA)+USART3(TX DMA)
Принимаю по юсарт2, побайтно, на скрости 115200. Пытаюсь передавать по юсарт3 через DMA, скорость...

STM32F4Discovery - ADC DMA и FSMC DMA
Привет всем. Вынужден опять обратиться за Вашей помощью :) Ситуация такая. 1. Дисплей...

95
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
14.10.2025, 18:01
Студворк — интернет-сервис помощи студентам
Eddy_Em, датчиков да, с ними проблем нет. Но говорю же, искал дисплей с готовым I2C - не нашел..
На TaoBao, еще где-то и прям по магазинам ходил. 2011-2013 года..
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,875
14.10.2025, 18:06
Цитата Сообщение от wizard41 Посмотреть сообщение
окромя SYNC (у SPI) в остальном они практически одинаковы.
там окромя "SYNS" вообще то синхронизация CLK
есть еще и MOSI Master Output Slave Input мастер выдает данные
MISO Maser Input Slave Output мастер принимает данные
т.е используется два провода на вход и выход
а в I2C один провод и на прием и на передачу
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
14.10.2025, 18:12
ValeryS, по принципу действия. Не физические линии.
Про CLK я говорил выше тоже.
0
 Аватар для COKPOWEHEU
4146 / 2724 / 433
Регистрация: 09.09.2017
Сообщений: 12,062
14.10.2025, 18:33
Цитата Сообщение от wizard41 Посмотреть сообщение
А вам принципиально надо было ответить?
Вы озвучили крайне странное утверждение, которое моему опыту противоречит. Естественно, я заинтересовался. Вдруг у SPI и I2C и правда есть что-то общее.
Цитата Сообщение от wizard41 Посмотреть сообщение
в остальном они практически одинаковы.
Да в чем они одинаковы-то?!
Цитата Сообщение от wizard41 Посмотреть сообщение
Т.е. если опыт в i2c - переделать в spi не проблема.
Где в SPI адрес ведомого, где адрес его регистра, где все эти ACK/NAK? Где там хоть что-то от I2C?!
0
335 / 129 / 8
Регистрация: 19.07.2024
Сообщений: 688
14.10.2025, 18:43
Цитата Сообщение от ValeryS Посмотреть сообщение
есть еще и MOSI Master Output Slave Input мастер выдает данные
MISO Maser Input Slave Output мастер принимает данные
т.е используется два провода на вход и выход
а в I2C один провод и на прием и на передачу
SPI тоже бывает полудуплексный. С объединёнными двунаправленными линиями данных. Причём - очень часто.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Вдруг у SPI и I2C и правда есть что-то общее.
Конечно есть: и то и другое - последовательные интерфейсы передачи данных.
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,875
14.10.2025, 19:02
Цитата Сообщение от jcxz Посмотреть сообщение
SPI тоже бывает полудуплексный. С объединёнными двунаправленными линиями данных.
покажь
0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,167
Записей в блоге: 19
14.10.2025, 19:19
Я ж говорю: у SPI больше общего с USART, чем с I2C. Усарты, кстати, тоже полудуплекс умеют.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
14.10.2025, 19:26
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Вы озвучили крайне странное утверждение
Да, возможно. И еще тут сказал об этом.
Говорил я больше про практику разработчика: одно на основании другого понимается просто.
Ну выразил мысль немного не так, что теперь - на 3 страницы будем это обсуждать? Извините, разучился доходчиво пояснять..
0
 Аватар для COKPOWEHEU
4146 / 2724 / 433
Регистрация: 09.09.2017
Сообщений: 12,062
14.10.2025, 20:42
Цитата Сообщение от jcxz Посмотреть сообщение
SPI тоже бывает полудуплексный.
Ну есть такая экзотическая настройка, ну и что?
Цитата Сообщение от jcxz Посмотреть сообщение
Конечно есть: и то и другое - последовательные интерфейсы передачи данных.
И USB последовательный, и UART, и CAN, и почти все остальные.
Вот только SPI или UART это именно интерфейсы, а I2C или USB - скорее протоколы.
Цитата Сообщение от ValeryS Посмотреть сообщение
покажь
У stm32f103 это бит BIDIMODE регистра SPI_CR1.
Цитата Сообщение от wizard41 Посмотреть сообщение
одно на основании другого понимается просто.
В том-то и дело, что нет. SPI существенно более простая штука, и в освоении I2C поможет не больше, чем какой-нибудь АЦП. Собственно, SPI это просто последовательная передача независимых байтов без всякой дисциплины обмена. А I2C это целый протокол, документирующий и правила работы нескольких устройств на одной шине, и порядок адресации, и конфликты, и собственно обмен. Разве что адресацию регистров внутрь I2C не оформили, но де-факто и это стандарт.
Цитата Сообщение от wizard41 Посмотреть сообщение
Извините, разучился доходчиво пояснять..
Теперь понятно.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
14.10.2025, 21:06
COKPOWEHEU, ну да, у всех своя голова и понимание, согласен.
Я, между прочим, первым как раз I2C освоил, а уж потом SPI и подобные. Даже лепил некий "симбиоз", т.к. очень подходили фишки i2c, типа арбитража и т.п., но не хватало аварийного железного сброса шины (всех мастеров и зависших слэйвов)..

Мне честно кажется(?), что тот кто освоил что-то из одного, то и с другим должен разобраться. Не велика наука.
В SPI тоже не все сразу втыкают в разность фаз сигналов и долго думают - почему не робит... Т.е. для кого и просто, а для кого труба..
0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,167
Записей в блоге: 19
14.10.2025, 21:37
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Разве что адресацию регистров внутрь I2C не оформили
Каждый производитель - кто в лес, кто по дрова! Вот, окучиваю эти самые I2C'шные датчики. Где-то нужно регистры читать, а где-то - тупо после получения 'rdy' (а бывает, что это - ACK, а пока вычисляет - NACK выдает) считать N байт данных. А еще бывают железки (тот же MLX90640) с 16-битными адресами регистров (и 16-битным содержимым). Благо, i2c'шный интерфейс в линуксе позволяет и такое, позволял бы преобразователь (а то начал я как-то, было дело, под tiny-i2c на STM32 эмулятор делать, мол, кернельный модуль-то уже есть; а не тут-то было: там такая жесть внутри творится, что плюнул, и запилил таки по-своему, через CDC). Кстати, непонятно, зачем преобразователи I2C в USB делают на основе HID. Подозреваю, что даже 1Мбод они таким корявым образом не потянут.

Добавлено через 3 минуты
Цитата Сообщение от wizard41 Посмотреть сообщение
не хватало аварийного железного сброса шины
Для некоторых "упоротых" датчиков помогает только сброс питания. Потому как одно дело, если он "ушел в себя", но при этом отвечает на широковещательные запросы и реагирует на стандартный сброс (6 по адресу 0). А вот если эта собака еще и SCL или SDA подтянула к нулю, и не отпускает, то только питанием и помогает сбросить.
Ну или вот столкнулся с датчиком SHT3x: в даташите написано, что после того, как он ACK на чтение ответит, считывай себе 6 байт данных и обрабатывай. Даже во всяких чужих кодах на просторах интернетов и в коде линуксового кернельного модуля так. А вот хрен: если тупо считать эти 6 байт и больше ничего не делать, он "уходит в себя" и перестает отвечать ACK на свой адрес. "Методом тыка" установил, что достаточно хоть какое-то обращение к нему сделать (например, сбросить регистр статуса), и все хорошо.

В общем, зачастую на платах с I2C'шными железяками я устанавливаю их питание через p-канальный мосфет, который можно, дрыгнув ногой, МК, отключить на несколько миллисекунд (если "там" много кондеров, лучше даже на 1 секунду для надежности), а потом опять включить. И подтяжки SDA/SCL обязательно уже после него делать, т.к. некоторым паразитам хватает питания через резисторы подтяжки (правда, я редко ставлю 4.7к - только если на шине исключительно одно устройство и скорость низкая, обычно подтяжки от 1к и даже до 333 Ом)!
0
 Аватар для COKPOWEHEU
4146 / 2724 / 433
Регистрация: 09.09.2017
Сообщений: 12,062
14.10.2025, 21:41
Цитата Сообщение от wizard41 Посмотреть сообщение
Мне честно кажется(?), что тот кто освоил что-то из одного, то и с другим должен разобраться. Не велика наука.
Как по мне, это касается контроллеров в целом. Если научился читать документацию, то с любым интерфейсом разобраться можно.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Где-то нужно регистры читать
Это да, "особенность" I2C. А может, так исторически сложилось. Там же не прописано, что I2C заточено на чтение - запись регистров. В результате запись-то ладно, а вот чтение по-уродски делается.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Кстати, непонятно, зачем преобразователи I2C в USB делают на основе HID
Наверное, потому что стандартного устройства нет, а значит будут проблемы с дровами. Тот же CDC на Тиньке по-честному ведь не сделать.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Подозреваю, что даже 1Мбод они таким корявым образом не потянут.
Думаю, они и предназначены максимум что-то протестировать. Или датчик опросить раз в вечность.
0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,167
Записей в блоге: 19
14.10.2025, 21:46
P.S. Глянул lsusb на CP2112: wMaxPacketSize 0x0040 1x 64 bytes и на Rx, и на Tx. То бишь у него потолок - 64Кбода! Офигеть, как мало!!!
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Там же не прописано, что I2C заточено на чтение - запись регистров.
Я тут с одним датчиком столкнулся (но, благо, не покупал - и не буду: вообще дичь): там поверх I2C сэмулировали modbus-rtu! Верх идиотизма!
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Тот же CDC на Тиньке по-честному ведь не сделать.
Ну, почему же? CDC и на USB1.0 бывают. Другое дело - USB ногодрыгом. Брр, ну и мерзость!
0
335 / 129 / 8
Регистрация: 19.07.2024
Сообщений: 688
14.10.2025, 23:31
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Ну есть такая экзотическая настройка, ну и что?
Это для вас она "экзотическая". Но если например ознакомитесь с даташитами на различные чипы SPI-FLASH, то узнаете, что она ни для кого кроме вас уже давно не экзотическая. А самая обыденная.

Добавлено через 1 минуту
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Если научился читать документацию, то с любым интерфейсом разобраться можно.
Вот именно. И про неэкзотичность полудуплекса SPI узнал.
0
 Аватар для COKPOWEHEU
4146 / 2724 / 433
Регистрация: 09.09.2017
Сообщений: 12,062
15.10.2025, 07:34
Цитата Сообщение от Eddy_Em Посмотреть сообщение
P.S. Глянул lsusb на CP2112: wMaxPacketSize 0x0040 1x 64 bytes
Оно HID? Если так, у точек свои ограничения на размер. Но не забывайте, что ограничения в одну транзакцию за фрейм там, скорее всего, нет.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Ну, почему же? CDC и на USB1.0 бывают.
Честные - не бывают. LS-точкам запрещено быть bulk. Хотя, конечно, никто не отменял vendor-specific устройства. USBASP ведь как-то работает.
0
62 / 187 / 31
Регистрация: 14.02.2013
Сообщений: 1,715
16.10.2025, 22:07
Всем кто в теме добрый день. Доканал этот i2c через DMA не знаю как там у профи но без прерывания на передачу у меня стабильности не вышло наверное нет опыта. Накодил библы правда в C++ но и ладно зато переносимо. hal тоже использует и прерывание и системные тики совместно с DMA это совершенно не к чему, только фигня в том что этот грёбаный дисплей переодически зависает.
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
extern I2C_HandleTypeDef hi2c1;
uint8_t deb;
uint8_t st7567a_IsDeviceReady(I2C_HandleTypeDef i2c) {
    for (uint8_t i = 0; i < 255; i++) {
        HAL_Delay(10);
        if (HAL_I2C_IsDeviceReady(&i2c, i, 3, 100) == HAL_OK) {
            return i;
        }
    }
    return 0;
}
 
extern uint32_t size_data, cout_data;
extern uint8_t *Buff_data, key_tx , i2c_adr_tmp;
extern I2C_HandleTypeDef *i2c_strucе_tmp;
extern DMA_HandleTypeDef dma_i2c1;
uint8_t I2C_Transmit_IT_ST7567A(I2C_HandleTypeDef *i2c, uint8_t Addr, uint8_t *Buff_data_tmp, uint32_t size_tmp)
{
    if(!(i2c->Instance->SR2 & I2C_SR2_BUSY))
    {
        i2c_adr_tmp = Addr;
        size_data = size_tmp;
        Buff_data = Buff_data_tmp;
        i2c_strucе_tmp = i2c;
        dma_i2c1.Instance->PAR = (uint32_t) &(hi2c1.Instance->DR);
        dma_i2c1.Instance->M0AR = (uint32_t) Buff_data_tmp;
        dma_i2c1.Instance->NDTR = size_tmp;
        __HAL_I2C_ENABLE_IT(i2c, I2C_IT_EVT | I2C_IT_ERR);
        i2c->Instance->CR1 |= I2C_CR1_START;
        return 2;
    }
    if((i2c->Instance->SR2 & I2C_SR2_BUSY))
    return 1;
 
    return 0;
}
 
 
uint8_t addr_i2c;
uint8_t Buffer_init_GLCD[11] = {Bias_Select_1_9, SEG_Direction_normal_dir, COM_Direction_normal_dir, Regulation_Ratio_5_0,
        Set_EV_CMD, 42, Power_Control_VB_ON, Power_Control_VR_ON, Power_Control_VF_ON};
uint8_t Buffer[100] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99};
uint8_t *Buff_data;
uint8_t test_mass = 0, err_res_flag = 0, key_tx = 0;
uint32_t tmp_cle, cout_data = 0, size_data = 0;
uint8_t i2c_adr_tmp;
void I2C_Init(void)
{
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
        HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
        __enable_irq ();
 
        __HAL_RCC_DMA1_CLK_ENABLE();
        //HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
        //HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
        HAL_NVIC_DisableIRQ(DMA1_Stream6_IRQn);
        dma_i2c1.Instance = DMA1_Stream6;
        dma_i2c1.Instance->CR = 0;
        dma_i2c1.Instance->CR |= DMA_CHANNEL_1;
        //dma_i2c1.Instance->CR |= DMA_SxCR_TCIE;
        dma_i2c1.Instance->CR |= DMA_SxCR_DIR_0;
        dma_i2c1.Instance->CR |= DMA_SxCR_MINC;
}
 
void I2C1_ER_IRQHandler(void)
{
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);
    if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_BERR))
        {
 
        }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_ARLO))
            {
 
            }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_AF))
            {
 
            }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_OVR))
            {
 
            }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_PECERR))
            {
 
            }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_TIMEOUT))
            {
 
            }
}
uint32_t tmp;
void I2C1_EV_IRQHandler(void)
{
    if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_BTF) && (i2c_strucе_tmp->Instance->SR1 & I2C_SR1_TXE))
    {
        DMA1->HIFCR |= DMA_HIFCR_CTCIF6;
        dma_i2c1.Instance->CR &= ~DMA_SxCR_EN;
        i2c_strucе_tmp->Instance->CR1 |= I2C_CR1_STOP;
        key_tx = 2;
    }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_SB))
        {
        tmp_cle = i2c_strucе_tmp->Instance->SR1;
        i2c_strucе_tmp->Instance->DR = i2c_adr_tmp;
        }
    else if((i2c_strucе_tmp->Instance->SR1 & I2C_SR1_ADDR))
            {
        tmp_cle = i2c_strucе_tmp->Instance->SR1 | i2c_strucе_tmp->Instance->SR2;
        i2c_strucе_tmp->Instance->CR2 |= I2C_CR2_DMAEN;
        dma_i2c1.Instance->CR |= DMA_SxCR_EN;
            }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.10.2025, 22:07

stm32f407+ADC+DMA. Проблема с DMA
Доброго дня! Новичок в stm, первый проект, начальные наброски, не понимаю,почему не работает эта...

STM32F4 I2C DMA CMSIS
Парни может кто писал под f4 скиньте рабочий код если не жалко

stm32 SPI+DMA или I2C внешнее АЦП
Есть у меня задача контролировать 3фазы линейно .Внутренний ацп не подходит наверное.Какое ацп...

передача данных USART + DMA и непонятные иероглифы
Всем привет! Есть проблема с передачей данных с МК на ПК через USORT + DMA. Ранее все работало...

stm32f4 SPI приём и передача данных по DMA
Посмотрел я примеры по SPI .Как правильно осуществить передачу данных и приём ?Особенно путаница с...


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

Или воспользуйтесь поиском по форуму:
96
Ответ Создать тему
Новые блоги и статьи
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
SUNO Ai - Река Без Дна
zorxor 31.07.2026
Автор стихотворения - астрофизик Марина Катыс Ссылка на сгенерированную музыкальную композицию: https:/ / suno. com/ song/ 6f6e5464-b290-4650-be6c-44c85f8d8013 Я говорю, что Время- как вода течет. . .
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru