16.03.2019, 00:55
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отправить массив по I2C через DMA на STM32F105 или F030?
Пока решил заняться STM32F030F4, для STM32F030F4 у меня работает только ногодрыг, не получается запустить аппаратный I2C, вот часть кода:
Нажмите, чтобы открыть спойлер
Код:
|
//--------------------------------------------------------------------------------------------
#define OLED_addr_127 0b00111100 //7-битный адрес OLED 0b01111000 = 0x78
//--------------------------------------------------------------------------------------------
RCC-›AHBENR |= RCC_AHBENR_GPIOAEN; //включаем тактирование
GPIOA-›OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10; /* (1) Open drain for I2C signals */
GPIOA-›AFR[1] = (GPIOA-›AFR[1] &~ (GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | (0x01 ‹‹ (1 * 4)) | (0x01 ‹‹ (2 * 4)); /* (2) AF1 for I2C signals */
GPIOA-›MODER = (GPIOA-›MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); /* (3) Select AF mode (10) on PA9 and PA10 */
//--------------------------------------------------------------------------------------------
void I2C_init(void)
{
RCC-›APB1ENR |= RCC_APB1ENR_I2C1EN; /* Enable the peripheral clock I2C2 */
RCC-›CFGR3 |= RCC_CFGR3_I2C1SW;
/* Configure I2C2, master */
/* (1) Timing register value is computed with the AN4235 xls file,
fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */
/* (2) Periph enable */
/* (3) Slave address = 0x5A, write transfer, 1 byte to transmit, autoend */
I2C1-›TIMINGR = (uint32_t)0x00B01A4B; /* (1) */
I2C1-›CR1 = I2C_CR1_PE; /* (2) */
I2C1-›CR2 = I2C_CR2_AUTOEND | (1‹‹16) | (OLED_addr_127‹‹1); /* (3) */
}
//--------------------------------------------------------------------------------------------
void I2C_StartCondition(void) //СТАРТ
{
I2C1-›CR2 |= I2C_CR2_START; /* Go */
}
//--------------------------------------------------------------------------------------------
void I2C_StopCondition(void) //СТОП
{
I2C1-›CR2 |= I2C_CR2_STOP;
}
//--------------------------------------------------------------------------------------------
void I2C_SendByte(unsigned char data) //ПЕРЕДАЧА БАЙТА и АСК
{
if((I2C1-›ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
{
I2C1-›TXDR = data; /* Byte to send */
I2C1-›CR2 |= I2C_CR2_START; /* Go */
}
//while (0 == (I2C1-›ISR & I2C_ISR_TXE)){}
}
//-------------------------------------------------------------------------------------------- |
может кто нибудь заметит ошибку, пока что в ЛА невидно вообще никакой активности на линиях I2C
они сидят в высоком уровне даже в момент ресета.
|
|
|
|
16.03.2019, 23:53
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отправить массив по I2C через DMA на STM32F105 или F030?
Нашёл ошибку - перепутал AF4 на котором сидит I2C в STM32F030F4 cо смещением номера вывода, правильно так:
Код:
|
GPIOA-›OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10; /* (1) Open drain for I2C signals */
GPIOA-›AFR[1] = (GPIOA-›AFR[1] &~ (GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | (4 ‹‹ ((9 - 8) * 4)) | (4 ‹‹ ((10 - 8) * 4)); /* (2) AF4 for I2C signals */
GPIOA-›MODER = (GPIOA-›MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); /* (3) Select AF mode (0b10) on PA9 and PA10 */ |
Поток пошёл, сейчас разбираюсь с порядком следования байт.
|
|
|
|
17.03.2019, 15:06
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отправить массив по I2C через DMA на STM32F105 или F030?
Возникли вопросы по регистру I2C1-›CR2 в STM32F030F4:
Cудя по дащиту (RM стр. 51 там есть секция "NBYTES" которая имеет размерность 8 бит и куда
записывается количество байт для передачи (максимум 255), т.е. по максимуму это выглядит так:
Код:
|
I2C1-›CR2 = I2C_CR2_AUTOEND | (256‹‹16) | (OLED_addr_127‹‹1); /* (3) */ |
я правильно понимаю, что этота секция не даст отправить вподряд более 255 байт между "старт-адрес-..байты...-стоп"?
Этот же регистр не даст передать по DMA более 255 байт вподряд, хотя у DMA есть регистр DMA1_Channel2-›CNDTR
куда можно записать уже 16 бит ?
|
|
|
|
17.03.2019, 15:56
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Как отправить массив по I2C через DMA на STM32F105 или F030?
Если читали, то должны были увидеть, что значение NBYTES действует только для autoend-режима, в котором автоматически формируется сигнал stop. Причем, NBYTES устроен таким образом, что после передачи 255 байт он может быть перезагружен (бит RELOAD) новым значением, и таким образом число передаваемых байт будет более 255.
В мануале приведена диаграмма передачи более 255 байт.
|
|
|
|
17.03.2019, 16:32
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отправить массив по I2C через DMA на STM32F105 или F030?
Спасибо, видел.
|
|
|
|
17.03.2019, 18:34
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отправить массив по I2C через DMA на STM32F105 или F030?
Ладно, допустим с выводом за раз, и без прерываний, массива более 255 байт на STM32F0 через DMA я пролетаю, но как отправить хотя бы 255 байт?
Вот так:
Нажмите, чтобы открыть спойлер
Код:
|
//--------------------------------------------------------------------------------------------
uint8_t screen_buff[512];
#define OLED_addr_127 0b00111100 //7-битный адрес OLED 0b01111000 = 0x78
//--------------------------------------------------------------------------------------------
void I2C_init(void)
{
RCC-›AHBENR |= RCC_AHBENR_DMA1EN; /* Enable the peripheral clock DMA1 */
/* DMA1 Channel4 I2C1_TX config */ /* Memory to peripheral */ /* 8-bit transfer */
DMA1_Channel2-›CPAR = (uint32_t)&(I2C1-›TXDR); /* (1) Peripheral address */
DMA1_Channel2-›CMAR = (uint32_t)screen_buff; /* (2) Memory address */
DMA1_Channel2-›CCR |= DMA_CCR_MINC | DMA_CCR_DIR; /* (3) Memory increment */
//------------------------------------------------------------------------------------
RCC-›APB1ENR |= RCC_APB1ENR_I2C1EN; /* Enable the peripheral clock I2C1 */
RCC-›CFGR3 |= RCC_CFGR3_I2C1SW;
/* Configure I2C1, master */
/* (1) Timing register value is computed with the AN4235 xls file,
fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */
/* (2) Periph enable */
/* (3) Slave address = 0x5A, write transfer, 1 byte to transmit, autoend */
I2C1-›TIMINGR = (uint32_t)0x00B01A4B; /* (1) */
I2C1-›CR1 = I2C_CR1_PE; /* (2) */
I2C1-›CR2 = I2C_CR2_AUTOEND | (255‹‹16) | (OLED_addr_127‹‹1); /* (3) */
}
//--------------------------------------------------------------------------------------------
void OLED_SendScreen(void)
{
if((I2C1-›ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
{
// I2C2-›TXDR = I2C_BYTE_TO_SEND; /* Byte to send */
//I2C2-›CR2 |= I2C_CR2_START; /* Go */
/* start transmission with DMA */
DMA1_Channel2-›CCR &=~ DMA_CCR_EN;
DMA1_Channel2-›CNDTR = 255; /* Data size */
DMA1_Channel2-›CCR |= DMA_CCR_EN;
I2C1-›CR2 |= I2C_CR2_START; /* Go */
}
}
//-------------------------------------------------------------------------------------------- |
не отправляется, в ЛА видно что есть старт, и правильно с нормальной скоростью отправляется адрес устройства,
и всё, больше никаких байт не идёт и стопа тоже нет.
Что не так?
Код практически целиком взят из снипетов (см. 1 пост), только изменён I2C2 на I2C1 и канал DMA c 4 на 2
(в снипетах код для STM32F072RBT)
Последний раз редактировалось Donker; 17.03.2019 в 21:19.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 15:48.
|
|