9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
1

STM32F4 I2C DMA CMSIS

26.08.2021, 13:13. Показов 830. Ответов 12
Метки нет (Все метки)

Парни может кто писал под f4 скиньте рабочий код если не жалко
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.08.2021, 13:13
Ответы с готовыми решениями:

Usart Dma cmsis
Подскажите что не так? уарт нормально работает, пытаюсь подключить дма ничего не получается void...

I2C CMSIS
всем привет кто работал с модулем I2C на STM32F103 используя только CMSIS скиньте пример...

CMSIS и STM32F4
Имеется Dyscovery c STM32F4 на борту. От SPL решил отказаться и использовать только CMSIS. CMSIS...

Stm32f4 cmsis
как настроить таймер stm32f4 cmsis

stm32f1 cmsis PWM-ADC-DMA
Как сделать так чтобы АЦП управляло ШИМом через ДМА.То есть АЦП в ДМА канал ШИМа в ДМА а как же...

12
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
09.09.2021, 09:55  [ТС] 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
void I2C::init (void)
{
 //Enable clock
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; //Port  clock
 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN ; //I2C1 clock
 //Port config PB6 - SCL BP7 - SDA
 GPIOB->OSPEEDR|= GPIO_OSPEEDER_OSPEEDR7 | GPIO_OSPEEDER_OSPEEDR6;  //Set speed, OSPEED 11 - very high speed
 GPIOB->MODER  |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER6_1;        //Alternate function, MODER 10
 GPIOB->OTYPER |= GPIO_OTYPER_OT_7 | GPIO_OTYPER_OT_6;              //set output to open drain
 GPIOB->PUPDR  |= GPIO_PUPDR_PUPDR7_0 | GPIO_PUPDR_PUPDR6_0;        //enable pull up resistors 
 GPIOB->AFR[0] |= GPIO_AFRL_AFRL7_2 | GPIO_AFRL_AFRL6_2;            //AF4 PB7, PB6
 //Enable I2C1 
 I2C1->CR2 = 42; // 100khz i2c clock
 I2C1->CCR = 210;
 I2C1->TRISE = 43;
 I2C1->CR1 |= I2C_CR1_ACK | I2C_CR1_PE;
}
 
 
void I2C::write(uint8_t addr, uint8_t data)
{
 I2C1->CR1 |= I2C_CR1_START;        
 while(!(I2C1->SR1 & I2C_SR1_SB));
 (void) I2C1->SR1;
    
 I2C1->DR = addr;
 while(!(I2C1->SR1 & I2C_SR1_ADDR)); //на этой строке зависает
 (void) I2C1->SR1;
 (void) I2C1->SR2;
    
 I2C1->DR = data;   
 while(!(I2C1->SR1 & I2C_SR1_TXE)); 
 I2C1->CR1 |= I2C_CR1_STOP;     
    
 I2C2->DR = data;   
 while(!(I2C1->SR1 & I2C_SR1_BTF)); 
 I2C2->CR1 |= I2C_CR1_STOP;
}
Добавлено через 11 минут
Нет даже на старте зависает(
C++
1
2
I2C1->CR1 |= I2C_CR1_START;     
while(!(I2C1->SR1 & I2C_SR1_SB));
0
1919 / 1235 / 123
Регистрация: 04.01.2010
Сообщений: 4,425
09.09.2021, 11:02 3
навскидку, у Вас не включается I2C. Для него нужен клок, но и бит Enable тоже. Что касается алгоритма - учитывая Ваши сомнения - лучше взять готовое исполнение I2C не на CMSIS, а на HAL'е, и с него взять настройку регистров, трассируя код по вызываемым функциям.
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
09.09.2021, 17:06  [ТС] 4
Да настройку регистров и так взял с LL

Добавлено через 34 минуты
На линии sda что то есть, scl молчит

Добавлено через 3 часа 59 минут
Использую I2C2 там такты идут
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
12.09.2021, 09:11  [ТС] 5
Вроде как поехало, окончательный вариант скину
Кликните здесь для просмотра всего текста
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
void I2C_2::init (void)
{
 //Enable clock
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; //Port  clock
 RCC->APB1ENR |= RCC_APB1ENR_I2C2EN ; //I2C1 clock
 //Port config PB10 -> SCL, BP11 -> SDA
 GPIOB->OSPEEDR|= GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR10;  //Set speed, OSPEED 11 - very high speed
 GPIOB->MODER  |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER10_1;        //Alternate function, MODER 10
 GPIOB->OTYPER |= GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_10;              //set output to open drain
 GPIOB->PUPDR  |= GPIO_PUPDR_PUPDR11_0 | GPIO_PUPDR_PUPDR10_0;        //enable pull up resistors 
 GPIOB->AFR[1] |= GPIO_AFRH_AFRH3_2 | GPIO_AFRH_AFRH2_2;              //AF4 PB11, PB10 
 //Enable I2C2 
 I2C2->CR2 = 42;  //168/4=42MHz
 I2C2->CCR = 210; 
 I2C2->TRISE = 43; 
 I2C2->CR1 |= I2C_CR1_PE;
}
 
 
void I2C_2::write(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C2->SR2 & I2C_SR2_BUSY);          //Wait if bus busy
 I2C2->CR1 |= I2C_CR1_START;               //Start generation
 while(!(I2C2->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C2->DR = addr;                          //Write slave address
 while(!(I2C2->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C2->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C2->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }
 (void)I2C2->SR2;                          //Read SR1
 while(len--)
      {
       while(!(I2C2->SR1 & I2C_SR1_TXE))     //Wait empty data register 
                  {
                         if(I2C2->SR1 & I2C_SR1_AF)    //Acknowledge failure
                       {
                          I2C2->CR1 |= I2C_CR1_STOP; //Stop generation
                          return;
                       }
                        }
             I2C2->DR = *data++;                 //Write data DR
             while(!(I2C2->SR1 & I2C_SR1_BTF));  //Wait data byte transfer succeeded
      }              
 I2C2->CR1 |= I2C_CR1_STOP;                //Stop generation
}
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
12.09.2021, 15:43  [ТС] 6
Всё работает затестил, ещё 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
void I2c1::init (void)
{
 //Enable clock
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; //Port  clock
 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN ; //I2C1 clock
 //Port config PB6 -> SCL, BP7 -> SDA
 GPIOB->OSPEEDR|= GPIO_OSPEEDER_OSPEEDR7 | GPIO_OSPEEDER_OSPEEDR6;  //Set speed, OSPEED 11 - very high speed
 GPIOB->MODER  |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER6_1;        //Alternate function, MODER 10
 GPIOB->OTYPER |= GPIO_OTYPER_OT_7 | GPIO_OTYPER_OT_6;              //set output to open drain
 GPIOB->PUPDR  |= GPIO_PUPDR_PUPDR7_0 | GPIO_PUPDR_PUPDR6_0;        //enable pull up resistors 
 GPIOB->AFR[0] |= GPIO_AFRL_AFRL7_2 | GPIO_AFRL_AFRL6_2;            //AF4 PB7, PB6
 //Enable I2C1 
 I2C1->CR2 = 42;  
 I2C1->CCR = 210; 
 I2C1->TRISE = 43; 
 I2C1->CR1 |= I2C_CR1_PE;
}
 
 
void I2c1::write(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy
 I2C1->CR1 |= I2C_CR1_START;               //Start generation
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->DR = addr;                          //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }
 (void)I2C1->SR2;                          //Read SR2
 while(len--)
      {
             I2C1->DR = *data++;                 //Write data DR
             while(!(I2C1->SR1 & I2C_SR1_TXE));  //Wait empty data register
      }         
 I2C1->CR1 |= I2C_CR1_STOP;                //Stop generation
}
 
 
void I2c1::read(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy
 I2C1->CR1 |= I2C_CR1_START;               //Start genera
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->CR1 |= I2C_CR1_ACK;                 //Enable acknowledge
 I2C1->DR = addr;                          //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }
 (void)I2C1->SR2;
 while(len--)
      {
       while(!(I2C1->SR1 & I2C_SR1_RXNE));   //Wait, data register is not empty
             *data++ = I2C1->DR;
      } 
 I2C1->CR1 |= I2C_CR1_STOP;                //Stop generation
 I2C1->CR1 &=~ I2C_CR1_ACK;                 //Disable acknowledge
}
0
63 / 64 / 2
Регистрация: 20.11.2016
Сообщений: 185
12.09.2021, 22:01 7
Вот раскопал в моих старых набросках мой код для SPI, делал три года назад, соединял проводами два SPI на одной плате. Проект делал через CubeMX, код работал

Вариант для SPI MASTER, файл main.c

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
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
 
UART_HandleTypeDef huart1;
 
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
#define DMA2_S0CR   (__IO uint32_t *)(0x40026400+0x0010)
#define DMA2_S0NDTR (__IO uint32_t *)(0x40026400+0x0014)
#define DMA2_S0PAR  (__IO uint32_t *)(0x40026400+0x0018)
#define DMA2_S0M0AR (__IO uint32_t *)(0x40026400+0x001C)
 
 
#define DMA2_S3CR   (__IO uint32_t *)(0x40026400+0x0058)
#define DMA2_S3NDTR (__IO uint32_t *)(0x40026400+0x005C)
#define DMA2_S3PAR  (__IO uint32_t *)(0x40026400+0x0060)
#define DMA2_S3M0AR (__IO uint32_t *)(0x40026400+0x0064)
 
#define Bufer_Size 10
 
#define LED1    GPIO_PIN_0 //  PC0
#define LED2    GPIO_PIN_3 //  PD3
 
 
uint8_t SendBuf[]="SPI 123456";
uint8_t ReceiveBuf[Bufer_Size];
uint8_t Test[]="Slave Send";
 
uint8_t Flag1=0, Flag2=0;
uint32_t Temp;
 
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART1_UART_Init(void);
 
 
 
// Stream of Receiver 
void DMA2_Stream0_init(void)
{
*DMA2_S0PAR=(uint32_t)&(SPI1->DR);  // write address of source
*DMA2_S0M0AR=(uint32_t)ReceiveBuf;
*DMA2_S0NDTR= Bufer_Size;   // write number of data
 
// setting of SxCR
*DMA2_S0CR|= (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 );  // canal 3
*DMA2_S0CR|= (DMA_SxCR_MINC);     // Memory increment mode
*DMA2_S0CR|= (DMA_SxCR_TCIE);     // enable interrupt of transfer completed
}
 
 
// Stream of Transmitter
void DMA2_Stream3_init(void)  
{
*DMA2_S3PAR=(uint32_t)&(SPI1->DR);  // write address of destination
*DMA2_S3M0AR=(uint32_t)SendBuf;
*DMA2_S3NDTR=  Bufer_Size;   // write number of data
 
// setting of SxCR
*DMA2_S3CR|= (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0);  // canal 3
*DMA2_S3CR|= (DMA_SxCR_DIR_0);     // memory-to-peripheral
*DMA2_S3CR|= (DMA_SxCR_MINC);     // Memory increment mode
*DMA2_S3CR|= (DMA_SxCR_TCIE);     // enable interrupt of transfer completed
}
 
static int Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength)
 
{
  while (BufferLength--)
  {
    if (*pBuffer1 != *pBuffer2)
    {
      return 0;
    }
    pBuffer1++;
    pBuffer2++;
  }  
  return 1;
}
 
 
void BufferClear(void)
{
  for (int i=0; i<Bufer_Size; i++)
  { 
    ReceiveBuf[i]=0;
  }
}
 
 
int main(void)
{  
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
 
  /* USER CODE BEGIN 2 */
  
//DMA2_Stream3_init();
//DMA2_Stream0_init();
 
HAL_Delay(250);    // pause for Master
 
SPI1->CR2|= (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);   // enable DMA mode
SPI1->CR1|= (SPI_CR1_SPE );     // enable SPI
 
 
  while (1)
  {
DMA2_Stream3_init();
DMA2_Stream0_init();
 
 Flag1=0; Flag2=0;   
*DMA2_S3CR|= (DMA_SxCR_EN);       // start stream SPI_Tx
*DMA2_S0CR|= (DMA_SxCR_EN);       // start stream SPI_Rx
 
 
HAL_Delay(1350); //
 
while (!(Flag1 && Flag2)) {};
 
 
if (Buffercmp( Test, ReceiveBuf, Bufer_Size))
{
   HAL_GPIO_TogglePin(GPIOC, LED1);
  }
 else 
 { 
  HAL_GPIO_WritePin(GPIOD, LED2, GPIO_PIN_RESET);
  }
//printf ("%s\n", ReceiveBuf);        // out received string
BufferClear();  // clear buffer
//HAL_Delay(1350); //
  }
}
 
 
/* SPI1 init function */
static void MX_SPI1_Init(void)
{
 
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
}
 
 
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
}
Добавлено через 6 минут
файл stm32f4xx_it

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
#define LISR_TCIF0 0x0020
#define LISR_TCIF3 0x08000000
 
 
extern uint8_t Flag1, Flag2;
 
 
/* USER CODE END 0 */
 
/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx;
 
/**
* @brief This function handles DMA2 stream0 global interrupt.
*/
void DMA2_Stream0_IRQHandler(void)   // Stream of Receiver
{
  /* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
  *DMA2_S0CR&= ~(DMA_SxCR_EN);     // stop of stream
  if (DMA2->LISR & LISR_TCIF0)     // if flag TCIF0  set
  DMA2->LIFCR|= DMA_LIFCR_CTCIF0;  // reset flag interrupt stream transfer complete
  Flag1=1;
 
  /* USER CODE END DMA2_Stream0_IRQn 0 */
  
  /* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
 
  /* USER CODE END DMA2_Stream0_IRQn 1 */
}
 
/**
* @brief This function handles DMA2 stream3 global interrupt.
*/
void DMA2_Stream3_IRQHandler(void)  // Stream of Transmitter
{
  /* USER CODE BEGIN DMA2_Stream3_IRQn 0 */
  *DMA2_S3CR&= ~(DMA_SxCR_EN);     // stop of stream
  if (DMA2->LISR & LISR_TCIF3)     // if flag TCIF3  set
  DMA2->LIFCR|= DMA_LIFCR_CTCIF3;  // reset flag interrupt stream transfer complete
  Flag2=1;
 
  /* USER CODE END DMA2_Stream3_IRQn 0 */
  
  /* USER CODE BEGIN DMA2_Stream3_IRQn 1 */
 
  /* USER CODE END DMA2_Stream3_IRQn 1 */
}
Добавлено через 16 минут
кажется ты совершаешь ошибку, пишешь процедуры передачи и чтения байта по I2C, а в случае DMA в этом нет необходимости прописывать эти процедуры. При использовании DMA достаточно указать ему адрес буфера, куда он будет принимать/передавать данные, размер буфера- количество передаваемых байтов и регистр данных соответствующей периферии например SPI1->DR, USART1->DR или, в твоем случае - I2C1->DR, и механизм DMA за тебя передаст эти данные)

P.S: чтобы написать этот код я читал раздел про DMA в даташите RM0090.pdf по английски...
1
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
14.09.2021, 07:11  [ТС] 8
Radikal_78Cейчас приделаю dma.
C++
1
*DMA2_S3CR&= ~(DMA_SxCR_EN);     // stop of stream
Тут можно не отключать поток, при передачи указанного объёма данных он отключиться сам, а вот флаг нужно скидывать(
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
15.09.2021, 11:31  [ТС] 9
Рассматриваю функцию HAL_I2C_Master_Transmit_DMA() в ней всё равно нужно прописывать I2C_CR1_START стартовый бит
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
16.09.2021, 07:32  [ТС] 10
Блин толк от DMA с 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
void I2c1::write(uint8_t addr, uint8_t *data, uint8_t len)
{
 uint8_t i = 0; 
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy
 I2C1->CR1 |= I2C_CR1_START;               //Start generation
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->DR = addr;                          //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }
 (void)I2C1->SR2;                          //Read SR2
 DMA1_Stream6->M0AR = (uint32_t)data;   
 DMA1_Stream6->NDTR = len;                 //Set len
 DMA1_Stream6->CR |= DMA_SxCR_EN;            //enable DMA
 while(DMA1_Stream6->CR & DMA_SxCR_EN);
 DMA1->HIFCR |= DMA_HIFCR_CTCIF6;   
 I2C1->CR1 |= I2C_CR1_STOP;         
}
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
16.09.2021, 16:49  [ТС] 11
Вот финальная версия затестил работает, старт, стоп к сожалению нужно самому прописывать, дма этого не может
Кликните здесь для просмотра всего текста
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
void I2c1::init (void)
{
 //Enable clock
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;                                  //Port  clock
 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN ;                                  //I2C1 clock
 RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;                                   //DMA1 clock
 //Port config PB6 -> SCL, BP7 -> SDA
 GPIOB->OSPEEDR|= GPIO_OSPEEDER_OSPEEDR7 | GPIO_OSPEEDER_OSPEEDR6;     //Set speed, OSPEED 11 - very high speed
 GPIOB->MODER  |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER6_1;           //Alternate function, MODER 10
 GPIOB->OTYPER |= GPIO_OTYPER_OT_7 | GPIO_OTYPER_OT_6;                 //Set output to open drain
 GPIOB->PUPDR  |= GPIO_PUPDR_PUPDR7_0 | GPIO_PUPDR_PUPDR6_0;           //Enable pull up resistors 
 GPIOB->AFR[0] |= GPIO_AFRL_AFRL7_2 | GPIO_AFRL_AFRL6_2;               //AF4 PB7, PB6
 //DMA RX config
 DMA1_Stream5->CR |= DMA_SxCR_CHSEL_0 | DMA_SxCR_PL_0 | DMA_SxCR_MINC; //Chanel 1, increment mode, periphery to men
 DMA1_Stream5->PAR  = (uint32_t)&(I2C1->DR);                           //Set address periphery         
 //DMA TX config
 DMA1_Stream6->CR |= DMA_SxCR_CHSEL_0 | DMA_SxCR_PL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0; //Chanel 1, increment mode, mem to periphery
 DMA1_Stream6->PAR  = (uint32_t)&(I2C1->DR);                                            //Set address periphery
 //Enable I2C1 
 I2C1->CR2 = I2C_CR2_DMAEN | 42;                                       //Enable DMA requests, set seripheral clock frequency
 I2C1->CCR = 210;                                                      //Set clock control register
 I2C1->TRISE = 43;                                                     //Set maximum rise time
 I2C1->CR1 |= I2C_CR1_PE;                                              //Enable I2C periphery 
}
 
 
void I2c1::write(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy 
 I2C1->CR1 |= I2C_CR1_START;               //Start generation
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->DR = addr;                          //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }           
 (void)I2C1->SR2;                          //Read SR2
 DMA1_Stream6->M0AR = (uint32_t)data;        //Set address buf
 DMA1_Stream6->NDTR = len;                 //Set len
 DMA1_Stream6->CR |= DMA_SxCR_EN;            //Enable DMA    
 while(!(I2C1->SR1 & I2C_SR1_BTF));        //Wait transmit all data
 DMA1->HIFCR |= DMA_HIFCR_CTCIF6;          //Clear DMA event    
 I2C1->CR1 |= I2C_CR1_STOP;                //Stop generation
} 
 
 
void I2c1::read(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy
 I2C1->CR1 |= I2C_CR1_START;               //Start genera
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->CR1 |= I2C_CR1_ACK;                 //Enable acknowledge
 I2C1->DR = addr;                          //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }
 (void)I2C1->SR2;                          //Read SR2
 DMA1_Stream5->M0AR = (uint32_t)data;        //Set address buf
 DMA1_Stream5->NDTR = len;                 //Set len
 DMA1_Stream5->CR |= DMA_SxCR_EN;            //Enable DMA   
 while(!(DMA1->HISR & DMA_HISR_TCIF5));    //Wait recive all data
 DMA1->HIFCR |= DMA_HIFCR_CTCIF5;          //Clear DMA event
 I2C1->CR1 |= I2C_CR1_STOP;                //Stop generation
 I2C1->CR1 &=~ I2C_CR1_ACK;                //Disable acknowledge
}
0
9 / 9 / 1
Регистрация: 15.08.2011
Сообщений: 285
Вчера, 16:36  [ТС] 12
Датчики по 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
static uint8_t ledPort = 0;   // ñîçäàåì ïåðåäåííóþ Ýêâèâàëåíò ðåãèñòðà ïîðòà
 
#define LCD_ADR  0x27  // àäðåñ LCD ïåðåõîäíèêà âñå 3 ïåðåìû÷êè îòïàÿíû 0õ27 
#define I2C_SendPocketLCD(x) lcd.write(LCD_ADR, x)   // ìàêðîñ îòïðàâêè ïàêåòîâ LCD
#define LCD_RS_SET  I2C_SendPocketLCD (ledPort |= 0x01)   // óñòàíîâêà ëîã. "1" íà ëèíèè RS
#define LCD_RS_CLR  I2C_SendPocketLCD (ledPort &=~ 0x01)  // óñòàíîâêà ëîã. "0" íà ëèíèè RS
#define LCD_RW_SET  I2C_SendPocketLCD (ledPort |= 0x02)   // óñòàíîâêà ëîã. "1"(çàïèñü) R/W*
#define LCD_RW_CLR  I2C_SendPocketLCD (ledPort &=~ 0x02)  // óñòàíîâêà ëîã. "0"(×òåíèå) R/W
#define LCD_E_SET   I2C_SendPocketLCD (ledPort |= 0x04)  // óñòàíîâêà ëîã. "1" íà ëèíèè E
#define LCD_E_CLR   I2C_SendPocketLCD (ledPort &=~ 0x04) // óñòàíîâêà ëîã. "1" íà ëèíèè ïîäñâåòêè
#define LCD_BT_SET  I2C_SendPocketLCD (ledPort |= 0x08)   // óñòàíîâêà ëîã. "1" íà ëèíèè ïîäñâåòêà âêë
#define LCD_BT_CLR  I2C_SendPocketLCD (ledPort &=~ 0x08)  // óñòàíîâêà ëîã. "0" íà ëèíèè ïîäñâåòêà âûêë
#define LCD_COM  0
#define LCD_DAT  1
 
 
 
void Lcd::write(uint8_t addr, uint8_t data)
{
 i2c1.write(addr, &data, 1);    
} 
 
 
void Lcd::putNibble(char t) // ïåðåäàåì íèáë 4 áèòà
{   
 t <<= 4;
 LCD_E_SET;
 cl.delayUs(100);   //50
 I2C_SendPocketLCD (ledPort|t);
 LCD_E_CLR;
 cl.delayUs(100);  //50
}
 
 
void Lcd::putByte(char c, char rs) // ïåðåäà÷è áàéòà â æêè (áàéò, êîì èëè äàí)
{   
 char highc = 0;
 highc = c >> 4;
 if (rs == 0) LCD_RS_CLR;  // rs = 0 - êîìàíäà
 else LCD_RS_SET;  // rs = 1 - äàííûå
 putNibble(highc);  // ïåðåäàåì íèáë 4 áèòà ñòàðøèå
 putNibble(c);      // ïåðåäàåì íèáë 4 áèòà ìëàäøèå
}
 
 
void Lcd::putChar(char c)   // âûâåñòè 1 ñèìâîë
{   
 char highc = 0;
 highc = c >> 4;
 LCD_RS_SET;              // rs = 1 - äàííûå
 putNibble(highc);
 putNibble(c);
}
 
 
void Lcd::clear(void)/* ôóíêöèÿ î÷èñòêè äèñïëåÿ è âîçâðàòà êóðñîðà â íà÷àëüíóþ ïîçèöèþ*/
{   
 putByte(0x01, LCD_COM);
 cl.delayUs(800); //1500
}
 
 
void Lcd::init(void)
{   
 cl.delayMs(15);
 LCD_BT_SET;                  // âêëþ÷àåì ïîäñâåòêó
 putByte(0x33, LCD_COM); // Ïîäãîòîâêà
 cl.delayMs(10);
 putByte(0x32, LCD_COM);
 cl.delayMs(5);
 putByte(0x28, LCD_COM);
 cl.delayMs(5);
 putByte(0x08, LCD_COM);  // Ïîëíîå âûêëþ÷åíèå äèñïëåÿ
 cl.delayMs(5);
 clear();                 // Î÷èñòêà äèñïëåÿ
 putByte(0x06, LCD_COM);  // Íàïðàâëåíèå ñäâèãà êóðñîðà - âïðàâî
 cl.delayMs(5);
 putByte(0x0C, LCD_COM);  // Âêëþ÷åíèå äèñïëåÿ
 LCD_RW_CLR;                  // çàïèñü r/w
}
 
/* 
0,0-------------------19,0
0,1-------------------19,1
20,0-------------------39,0
20,1-------------------39,1
*/
 
void Lcd::gotoxy(uint8_t x, uint8_t y)   // ìåñòî, ñòðîêà
{   
 char adr;
 adr = 0x40 * y + x;    // s-1   ïåðâàÿ ñòðîêà    0x7F + 1 = 0x80  (((((row)&1)*0x40)+((((row)&3)>>1)*0x14)+(col))|128)
 adr |= 0x80;       // èíà÷å 2 âòîðàÿ ñòðîêà  0xÂF + 1 = 0xÑ0
 putByte(adr, LCD_COM);
}
 
 
void Lcd::putString (const char *str)   // âûâîäèì ñòðîêó ïîêà åñòü òåêñò
{  
 uint8_t len = strLen(str); 
 while(len--) putChar(*str++);
}


Добавлено через 27 минут
Заработало, но почему вместо адреса 0x27 нужно указывать 0x4E

Добавлено через 1 час 34 минуты
типо на 1 бит сдвинуть влево

Добавлено через 37 минут
C++
1
I2C2->DR = addr << 1;
Добавлено через 18 минут
финал релиз, код может кому пригодиться
Кликните здесь для просмотра всего текста
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
 
void I2c1::init (void)
{
 //Enable clock
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;                                  //Port  clock
 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN ;                                  //I2C1 clock
 RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;                                   //DMA1 clock
 //Port config PB6 -> SCL, BP7 -> SDA
 GPIOB->OSPEEDR|= GPIO_OSPEEDER_OSPEEDR7 | GPIO_OSPEEDER_OSPEEDR6;     //Set speed, OSPEED 11 - very high speed
 GPIOB->MODER  |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER6_1;           //Alternate function, MODER 10
 GPIOB->OTYPER |= GPIO_OTYPER_OT_7 | GPIO_OTYPER_OT_6;                 //Set output to open drain
 GPIOB->PUPDR  |= GPIO_PUPDR_PUPDR7_0 | GPIO_PUPDR_PUPDR6_0;           //Enable pull up resistors 
 GPIOB->AFR[0] |= GPIO_AFRL_AFRL7_2 | GPIO_AFRL_AFRL6_2;               //AF4 PB7, PB6
 //DMA RX config
 DMA1_Stream5->CR |= DMA_SxCR_CHSEL_0 | DMA_SxCR_PL_0 | DMA_SxCR_MINC; //Chanel 1, increment mode, periphery to men
 DMA1_Stream5->PAR  = (uint32_t)&(I2C1->DR);                           //Set address periphery         
 //DMA TX config
 DMA1_Stream6->CR |= DMA_SxCR_CHSEL_0 | DMA_SxCR_PL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0; //Chanel 1, increment mode, mem to periphery
 DMA1_Stream6->PAR  = (uint32_t)&(I2C1->DR);                                            //Set address periphery
 //Enable I2C1 
 I2C1->CR2 = I2C_CR2_DMAEN | 42;                                      //Enable DMA requests, set seripheral clock frequency
 I2C1->CCR = 210;                                                      //Set clock control register
 I2C1->TRISE = 43;                                                     //Set maximum rise time
 I2C1->CR1 |= I2C_CR1_PE;                                              //Enable I2C periphery 
}
 
 
void I2c1::write(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy 
 I2C1->CR1 |= I2C_CR1_START;               //Start generation
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->DR = addr << 1;                     //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }           
 (void)I2C1->SR2;                          //Read SR2
 DMA1_Stream6->M0AR = (uint32_t)data;        //Set address buf
 DMA1_Stream6->NDTR = len;                 //Set len
 DMA1_Stream6->CR |= DMA_SxCR_EN;            //Enable DMA    
 while(!(I2C1->SR1 & I2C_SR1_BTF));        //Wait transmit all data
 DMA1->HIFCR |= DMA_HIFCR_CTCIF6;          //Clear DMA event    
 I2C1->CR1 |= I2C_CR1_STOP;                //Stop generation
} 
 
 
void I2c1::read(uint8_t addr, uint8_t *data, uint8_t len)
{
 while(I2C1->SR2 & I2C_SR2_BUSY);          //Wait if bus busy
 I2C1->CR1 |= I2C_CR1_START;               //Start genera
 while(!(I2C1->SR1 & I2C_SR1_SB));         //Wait start condition generated
 I2C1->CR1 |= I2C_CR1_ACK;                 //Enable acknowledge
 I2C1->DR = (addr << 1) | 1;               //Write slave address
 while(!(I2C1->SR1 & I2C_SR1_ADDR))        //Wait send addsess
      {
           if(I2C1->SR1 & I2C_SR1_AF)          //Acknowledge failure
                 {
                    I2C1->CR1 |= I2C_CR1_STOP;       //Stop generation
                    return;
                 }
            }
 (void)I2C1->SR2;                          //Read SR2
 DMA1_Stream5->M0AR = (uint32_t)data;        //Set address buf
 DMA1_Stream5->NDTR = len;                 //Set len
 DMA1_Stream5->CR |= DMA_SxCR_EN;            //Enable DMA   
 while(!(DMA1->HISR & DMA_HISR_TCIF5));    //Wait recive all data
 DMA1->HIFCR |= DMA_HIFCR_CTCIF5;          //Clear DMA event
 I2C1->CR1 |= I2C_CR1_STOP;                //Stop generation
 I2C1->CR1 &=~ I2C_CR1_ACK;                //Disable acknowledge
}
0
1919 / 1235 / 123
Регистрация: 04.01.2010
Сообщений: 4,425
Сегодня, 07:46 13
Цитата Сообщение от Korbofos Посмотреть сообщение
Заработало, но почему вместо адреса 0x27 нужно указывать 0x4E
... так во многих библиотеках, тоже сталкивался. По идее проблема в том, что LSB в байте адреса при отправке указывает на направление запроса - чтение или запись. То есть физически у вас пакет отправляется на адрес 0x4E при чтении данных и 0x4F - при записи (ну, или наоборот). В итоге - одни библиотеки требуют сдвинутый адрес, другие - обычный.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Сегодня, 07:46

Помощь в написании контрольных, курсовых и дипломных работ здесь.

stm32f4 cmsis шим
/* * main.c * * Created on: 10 лист. 2019 р. * Author: Ivan */ #include&quot;main.h&quot; ...

STM32F4 USB CMSIS
Я понимаю сейчас наверное скажите: &quot;Куда ты полез школьник, иди лучше уроки учи или мамке по дому...

ADC через CMSIS на STM32F4
Всем привет Пытаюсь запустить ADC через CMSIS на STM32F4 и не идут данные с АЦП в чем может быть...

Использование функций CMSIS-DSP в STM32f4
Приветствую. Проблема такова, написал я программу с использованием DSP функций, входящих в CMSIS,...

stm32f4 cmsis задержка для LCD
как организовать задержку на cmsis правильно для LCD.Спецы подскажите аматору?


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.