ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
1337535
Связанные сообщения
Ch32V003
[09.01.2024] по ходу подпрыгивании на тему "подъема-взлета" ch32v003 всунул в него CoreMark. промерил...2024-01-09
Пришел десяток CH32V003 в soic8 с Ali по 13 руб. Показались удобными для всяческой мелкой хренотени. Ну и как у китайцев положен...2023-07-26
Столько полезной информации...2023-07-03
klen (07.08.2023 01:19 - 09.08.2023 16:55, просмотров: 14768)
[заработало] у кого есть удачный опыт "i2c заработало в ch32v003" ? промудохалсо весь выходной... выводы неоднозначные. может что то делаю не так? 

1. подключил физически стандартный 0,96 oled модуль в варианте i2c к ногам pc5 pc6. подтяжки 1кОм.

2. есть рабочий код для gd32v103 , работает через dma

3. судя по документации поведение модулей i2c одинаково ( особливо я смотрел на поведение битов в двух статусных регистрах при их чтении )

4. закомпилял ...

5. процедура выставления старта и адреса слейва проходит без проблем. далее при записи байта в регистр данных он отправляется но не выставляется бит TXE, что приводит к зацикливанию. что для ручной записи второго байто что для dma. никакие задержки в разных местах не смогли на что то повлиять.

6. итересное - если все делать пошагово в отладчике - тоже зацикливается, но если открыть окошко с просмотром регистров переферии - а именно регистры статуса i2c - то все начинает работать. кровь из глаз.


в данной стадии я ощущаю себя слепым мудрецом ощупывающим неизвестное животное слон.

по наблюдениям делаю заключение - чтение регистров статуса через отладочный интерфейс меняет поведение state-машины i2c


исходя из моего понимая логики работы i2c - а именно сброс одних битов и не сброс других при чтении статусных регистров (к примеру TXE не сбрасывается при чтении) строится правильный код. отладочный интерфейс должен уметь читать значения регистров но "скрытно". чтоб state-машина ничего не заметила и не сбросила биты мимо исполняймого кода с одной стороны, и то что я вижу происходит совсем не так, напрашиваются два вопроса.


1. где я баран?

2. а не перепутали китайцы что то в отладочном интерфейсе. касательно чтения статусных регистров - стандартно как процессор по шине этого напрямую делать нельзя ?

3. а где собсно errata на микросхему... у них даже ревизий нет. напоминает анегдот: крузак100 и УАЗ буханка были выпушены в 60году. крузак100 претерпел 16 модификация с целью исправления косяков. буханка сразу получилась ахуэнной!


вот кусок кода записи массива данных на oled для примерного понимая как я это делаю

static inline void_write_data(const uint8_t* buf, const size_t count)
    {
        i2c1.busy_wait(); // ожидания состяния idle на шине
        i2c1.start_set(); // "start" на шину
        i2c1.start_condition_send_wait(); // ожидание состояния "start" на шине
        i2c1.slave_write_address_send(i2c_oled_address7); // запись адреса ведомого на шину, тип ранзакции - запись
        i2c1.master_mode_tx_select_wait(); // ожидание битов {ADDR TXE} {MSL  BUSY TRA}

       
        i2c1.data = data_control_byte; // запись первого байта, переключение ssd130x в режим преима данных

        // установка dma для записи содержимого frame-буфера oled
  	dma1.channel_i2c1_tx.memory_address = const_cast*>


[обновлено 09.08.2003]

заработало с dma, взял измором. завелось на 380кГц. тонкость по всей видимости была в том что нужно еще и бит выставки адреса на шину сбрасывать, а оно требует последовательного чтения status1 и сразу за ним status2.

примеры из интернета незаработал не один - хотя у них якобы гожий рабочий гаджет

https://github.com/bitbank2/Pocket_CO2

заклинивало в других местах - не как у меня.

может кому интересно будет.




мой новый код код который "смог". важна последовательность чтений status1 и status2, поскольку эти чтения являются частью управления стейт машиной i2c

   
static inline void init() { dma1.clock_enable(); dma1.channel_i2c1_tx.reset(); dma1.channel_i2c1_tx.config.write( dma_channel_t::config_t::state_t::disable, dma_channel_t::config_t::tx_complete_interrupt_t::enable, dma_channel_t::config_t::direction_t::memory_to_peripheral, dma_channel_t::config_t::memory_increment_mode_t::enable, dma_channel_t::config_t::peripheral_data_size_t::byte, dma_channel_t::config_t::memory_data_size_t::byte, dma_channel_t::config_t::priority_level_t::high ) ; dma1.channel_i2c1_tx.pfic_enable(); dma1.channel_i2c1_tx.peripheral_address = &i2c1.data ; rcc.apb2_peripheral_clock.modify( rcc_t::apb2_peripheral_clock_t::afio_t::enable, rcc_t::apb2_peripheral_clock_t::gpioc_t::enable ) ; afio.i2c1_remap_scl_pc5_sda_pc6(); gpioc.config0.modify( gpioc_t::config0_t::pin5_mode_t::output_50mhz, gpioc_t::config0_t::pin5_output_type_t::alternate_open_drain, gpioc_t::config0_t::pin6_mode_t::output_50mhz, gpioc_t::config0_t::pin6_output_type_t::alternate_open_drain ) ; i2c1.clock_enable(); i2c1.clock_reset(); // 965кГц 9,36мс на обновление фрейм буфера i2c1.speed_fast(); i2c1.duty_cycle_fast_mode_duty_12div33(); i2c1.clock(0x2); i2c1.peripheral_clock(36) ; i2c1.addr_config(i2c1_t::address1_t::slave_address_mode_t::mode_7bit , i2c_self_address7); i2c1.dma_enable(); i2c1.enable(); i2c1.ack_enable(); dma1.channel_i2c1_tx.enable(); }

template <const uint8_t oled_transaction_type> __ais__ auto write(const uint8_t* buf, const size_t count) { i2c1.busy_wait(); // ожидания состяния idle на шине i2c1.start_set(); // "start" на шину i2c1.start_condition_send_wait(); // ожидание состояния "start" на шине i2c1.slave_write_address_send(i2c_oled_address7); // запись адреса ведомого на шину i2c1.adress_send_recv_match_wait_clear(); // ожидание и сброс флага adress_send_recv_match i2c1.tx_empty_wait(); i2c1.data = oled_transaction_type ; dma1.channel_i2c1_tx.memory_address = const_cast<void*>(static_cast<const void*>(buf)); dma1.channel_i2c1_tx.counter=count ; dma1.channel_i2c1_tx.enable(); // запуск передачи }



irq_handler_hpei(dma1_channel6) { dma1.channel_i2c1_tx.tx_complete_interrupt_flag_clear() ; i2c1.byte_transmission_completed_wait(); // ожидание передачи крайнего в транзакции байта i2c1.stop_set(); // "stop" на шину i2c1.stop_wait(); // ожидание "stop condition" в master режиме }

раскачалось до 956кГц клок на 1кОм подтяжка, и время обновления всего кадрового буфера ssd130x 9.3мс. я свои 100 Гц кадров в секунду получил!