ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
26 апреля
963127 Топик полностью
Nikolay_Po (07.12.2019 17:47 - 19:48, просмотров: 332) ответил Nikolay_Po на Я как-то устал добиваться от готовых библиотек бесперебойности работы шины. Нужно было, чтобы после закорачивания SCL, SDA, GND гвоздём в произвольных комбинациях связь восстанавливалась мгновенно.
Чтобы не быть голословным, см. вложения. Работает на PIC24HJx dsPIC30F60x, на остальных не проверял, должно с минимальной доработкой. P.S. Совсем забыл. Есть блокирующий код - задержки в процедуре восстановления связи. Ещё используется таймер для определения зависания шины. Остальное очевидно и мне было очень удобно. Очередь на 4 сообщения (три ведомых на шине) и в неё в произвольном порядке лились команды и данные. К примеру, шилась EEPROM в то же время по шине шли команды на смену усиления PGA и подстройку ЦАПа смещения. И это дело было равнодушно к электромагнитной обстановке. Процесс к коротким отказам шины не критичен, в EEPROM информация писалась с CRC32 и сверкой чтением после записи. P.P.S. Чтобы лучше понять логику работы с запросом транзакции и его блоками, вот пример чтения из I2C EEPROM. Здесь в одну транзакцию "Transaction Request" объединены два блока "Transaction Request Block" (TRB), один запись, другой - чтение. При этом сами блоки и их данные определяются в месте вызова, так как использующий шину код лучше знает, чего и сколько нужно отправить и принять. Блоки одной транзакции должны быть размещены в общем буфере последовательно. Производится чтение или запись определяется выбором функции создания блока, I2C_MasterWriteTRBBuild() или I2C_MasterReadTRBBuild(). В каждом блоке описывается количество данных и передаётся указатель на данные. Когда цепочка блоков (в примере - два) готова, указатель на неё с количеством блоков передаётся фунции создания транзкции, I2C_MasterTRinsert(). При этом сама транзация занимает место в очереди, которая определена в коде i2c.c и размер которой зависит от потребностей всех задач шины. Отмечу, что статус транзакции обновляется для каждой транзакции отдельно, так как у каждой транзакции может быть свой статус - передаётся указателем при создании транзакции. В примере код блокирующий, но ничто не мешает опрашивать статус транзакции в цикле машины состояний или другим образом. Учитыывая меры против зависания шиниы (таймер), код, несмотря на наличие while(), блокирует процессор лишь на ограниченное время - на заданное количество попыток. #include "i2c.h" static I2CTRB EEPROM_I2CTRB[2]; //Read and/or write operations to be placed in I2C queue static volatile RequestStatus_t I2CmsgStat; //I2C message status int eeprom_read(uint8_t *Data, uint16_t DataAddress, uint8_t Length) { uint8_t Address[2]; //The buffer for two bytes of EEPROM data address Address[0] = DataAddress >> 8; //Setup EEPROM data address Address[1] = DataAddress & 0xFF; // //Create EEPROM address setup operation, an I2C write block, first I2C_MasterWriteTRBBuild(&EEPROM_I2CTRB[0], Address, 2, EEPROM_I2C_Addr); //Then create data reading operation, an I2C read block I2C_MasterReadTRBBuild(&EEPROM_I2CTRB[1], Data, Length, EEPROM_I2C_Addr); //Now I2C transaction request is ready for queueing unsigned Trial = I2Ctrials5ms; //Maximum possible number of writes in 5ms //The code will try to communicate the EEPROM until the success or the //timeout by trials number if the trials were not successfull, for example, //if EEPROM was busy by write operation. do { //Trial repeat loop if (!Trial--) { //Check for EEPROM access timeout //All tries are out without of a success. The EEPROM was not //answered in a time more than 5ms or there was some other problems //on I2C bus. return (1); } //Put data address writing and data reading into I2C queue SET_AND_SAVE_CPU_IPL(i2c_eeprom_old_ipl, I2Cpriority); I2C_MasterTRinsert(2, //The number of transactions in a block &EEPROM_I2CTRB[0], //The transaction block itself with two transcactions &I2CmsgStat); //The status of transaction to test RESTORE_CPU_IPL(i2c_eeprom_old_ipl); //Restore CPU priority level //Wait for transaction block completeness while (I2CmsgStat == I2C_PENDING); //Wait for transaction //pending and execution } while (I2CmsgStat != I2C_COMPLETE); //Repeat until the success or a timeout //EEPROM data reading is complete return (0); //Return OK }