Пишу код для слейва в виде Attiny2313, суть такова: мастер AT90CAN128 отправляет значение частоты и номер генератора по SPI, а слейв принимает сигнал по USI и на основе полученных значений выдает частоту на выходе(переменная fG отвечает за частоту, nG за номер ножки на выходе). Генерация частоты происходит на таймере1, в функции SetUpTim1A(unsigned int Foc) - подставляем значение частоты fG, там расчитывается значение регистра OCR1A. В функции void set_out_pin (unsigned char num) - подставляем значение nG, эта функция подставляет значение заданного вывода МК в функцию прерывания и таким образом генерируется частота. В функции SpiSlaveInit() - выставляются настройки USI и разрешаются внешние прерывания и прерывания по переполнению. В функции прерывания interrupt [EXT_INT1] void ext_int1_isr(void) - проверяется состояние пина PD3: при Falling edge - разрешаются прерывания по переполнению таймера USI, при Rising edge -запрещаются. В функции interrupt [USI_OVERFLOW] void usi_ovf_isr(void) - каждое прерывание считывается по байту входящей информации, и на основании полученных данных устанавливается значение fG и nG, ну и соответственно генерируется чатота на выходе. Но даже без мастера он дергает всеми пинами в произвольном порядке. Проблема заключается в том, что частота присутствует на выходе PB0 тиньки, и она не соответствует отправленной по SPI. Код мастера:
#define CS PORTD3 // Chip select #define DO PORTB5 // MISO or Data Out #define USCK PORTB7 // Clock
typedef union { unsigned long int w ; // w as WORD unsigned int h[2]; // h as HALF-WORD unsigned char b[4]; // b as BYTE } Union32; Union32 dFi;
unsigned int fG; unsigned char nG; unsigned int N[]={1,8,64,256,1024}; unsigned char flag_RT = 0; unsigned char ch_num = 0;
volatile char reqID = 0; // This is for the first byte we receive, which is intended to be the request identifier volatile unsigned char index = 0; // this is to send back the right element in the array
void SpiSlaveInit() { #asm("cli") USICR = ((1<<USIWM0)|(1<<USICS1)); // Activate 3- Wire Mode and use of external clock but NOT the interrupt at the Counter overflow (USIOIE) PORTD |= 1<<CS; // Activate Pull-Up resistor on PD3 PCMSK|=1<<CS; // Active Interrupt on PD3 GIMSK|=1<<PCIE; // General Interrupt Mask Register / PCIE bit activates external interrupts #asm("sei") }
// If edge is falling, the command and index variables shall be initialized // and the 4-bit overflow counter of the USI communication shall be activated: reqID = 0; index = 0; flag_RT = 0; USICR |= (1<<USIOIE); USISR = 1<<USIOIF; // Clear Overflow bit } else{ // If edge is rising, turn the 4-bit overflow interrupt off: USICR &= ~(1<<USIOIE); } }
interrupt [USI_OVERFLOW] void usi_ovf_isr(void) { switch(reqID) { case 0: ch_num = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; break; case 1: dFi.b[0] = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; break; case 2: dFi.b[1] = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; break; case 3: dFi.b[2] = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; flag_RT = 1; break; } }
1 Смысл плодить темы, не закончив предыдущую? 2 Схема не читается абсолютно. 3 Было ведь написано, что свич у вас заклинен на 0 кейсе. Значит регулировка частот просто недоступна. Зато доступен выбор пина порта В, для выхода генерации, если мастер со славой нормально контачат. Этот вариант вам и предлагалось опробовать и отладить. Потом уже занялись бы частотой.
1 Смысл плодить темы, не закончив предыдущую? 2 Схема не читается абсолютно. 3 Было ведь написано, что свич у вас заклинен на 0 кейсе. Значит регулировка частот просто недоступна. Зато доступен выбор пина порта В, для выхода генерации, если мастер со славой нормально контачат. Этот вариант вам и предлагалось опробовать и отладить. Потом уже занялись бы частотой.
1) Я считаю, что тема достаточно сложная и интресная, поэтому вынес отдельно. Также не видел похожих тем. 2) Скинул нормальную. 3) Я не знаю как мне проверить нормально ли они контачат.
Добавлено after 5 minutes 50 seconds: Нашел ошибку в функции иницилзаци USI:
Код:
void SpiSlaveInit() { #asm("cli") USICR = ((1<<USIWM0)|(1<<USICS1)); // Activate 3- Wire Mode and use of external clock but NOT the interrupt at the Counter overflow (USIOIE) PORTD |= 1<<CS; // Activate Pull-Up resistor on PD3 GIMSK|=1<<INT1; // General Interrupt Mask Register //ISC11/ISC10 MCUCR #asm("sei") }
Теперь внешние прерывания INT1 работают. В протеусе теперь показывает на всех пинах PB0,PB1,PB2 напряжение. Частота не генерируется.
Вложения:
Комментарий к файлу: Добавил архив с схемой(P-CAD) и прошивками ATTINY2313 и AT90CAN128. KD8105.rar [511.15 KiB]
Скачиваний: 75
PCAD-а у меня нет, так что схему все одно не увижу. Универсальный вариант - конвертировать в pdf. Акробат есть практически у всех.
Цитата:
3) Я не знаю как мне проверить нормально ли они контачат.
Порт В у вас практически пуст, за исключением 5 и 7 битов. Посылаете мастером любой из доступных номеров пина и смотрите светодиодом, осциллографом или что там у вас есть - "переехал" ли генератор на заданную ногу Attiny2313. Этим самым выясните - есть ли вообще хоть какой-то обмен данными, и реагирует ли на него Attiny2313. Отладите эту часть, а потом уже можно заняться и частотой, так как, похоже, придется усложнить протокол обмена данными, включив него и значения reqID. Ну и такие схемы лучше отлаживать в железе. Протеус он такой протеус...
Открыта удобная площадка с выгодными ценами, поставляющая весь ассортимент продукции, производимой компанией MEAN WELL – от завоевавших популярность и известных на рынке изделий до новинок. MEAN WELL.Market предоставляет гарантийную и сервисную поддержку, удобный подбор продукции, оперативную доставку по России.
На сайте интернет-магазина посетители смогут найти обзоры, интересные статьи о применении, максимальный объем технических сведений.
Добавлено after 1 hour 21 minute 58 seconds: Со стороны мастера все впорядке, он что-то отправляет и это похоже на управляющий сигнал. На стороне слейва только порт PB0 горит, но частоты там нет.
Добавлено after 44 minutes 31 second: Ниже прикрепил осцилограмы выходных сигналов.
Добавлено after 40 minutes 42 seconds: С мастера все сигналы идут нормально, судя по осцилограмме, а вот слейв вообще не реагирует. Изменил регистры прерываний по внешнему сигналу GIMSK = 1<<INT1, на GIMSK |= 1<<PCIE - маска прерываний по измению уровня входящего сигнала и вернулся к прежней проблеме - 4 Гц на PB0. В прерываниях пробовал дергать пинами и пришел к выводу, что оба прерывания не работают. Также убирал функции расчёта частоты и прерываний Таймера1, результат тот же. Ещё нашел ошибку в том, что неправильно обозвал функцию прерывания по изменению уровня на входе, ошибку исправил - результат тот же.
Продукция MOSO предназначена в основном для индустриальных приложений, использует инновационные решения на основе более 200 собственных патентов для силовой электроники и соответствует международным стандартам. LED-драйверы MOSO применяются в системах наружного освещения разных отраслей, включая промышленность, сельское хозяйство, транспорт и железную дорогу. В ряде серий реализована возможность дистанционного контроля и программирования работы по заданному сценарию. Разберем решения MOSO
подробнее>>
MOHCTEP
Заголовок сообщения: Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Уже какой-то конструктив... Теперь понятно, что слейв просто не понимает или не видит мастера. Тут возможно или частота обмена данными не "в размер" или USI неверно настроен.
Тут возможно или частота обмена данными не "в размер" или USI неверно настроен.
По идее частота никак не должна влиять, ведь у меня постоянно идет опрос ножки PD3(CS) при изменении уровня логического сигнала, а прерывание PCIE - управляет прерываниями по переполнению 4-х битного таймера(включает/выключает их), а вот в функции прерывания этого таймера побайтово должны приниматься сигналы и я уже в мейне подставляю полученые байты в переменную fG и nG и там уже высчитывается значение частоты и номер вывода. Еще и для протеуса на работе в компе CPU не хватает и он инфу не в реал тайме отображает, попробую дома прогнать, может результат изменится, но я так думаю, что наврятли.
Добавлено after 32 minutes 53 seconds: Вернулся к внешним прерываниям INT1:
Код:
void SpiSlaveInit() { #asm("cli") USICR = ((1<<USIWM0)|(1<<USICS1)); // Activate 3- Wire Mode and use of external clock but NOT the interrupt at the Counter overflow (USIOIE) GIMSK |= 1<<INT1; MCUCR |= 1<<ISC10; #asm("sei") }
// If edge is falling, the command and index variables shall be initialized // and the 4-bit overflow counter of the USI communication shall be activated: reqID = 0; index = 0; flag_RT = 0; USICR |= (1<<USIOIE); USISR = 1<<USIOIF; // Clear Overflow bit } else{ // If edge is rising, turn the 4-bit overflow interrupt off: USICR &= ~(1<<USIOIE); } }
В регистре MCUCR установил также прерывания при любом изменении логического уровня на INT1, теперь есть хоть какая-то реакция на изменения входных данных от мастера, при изменении переменных nG и fG в прошивке мастера - меняются выходы и частота на слейве. Но я не знаю пока как это структурировать.
Последний раз редактировалось warptred12 Ср июн 07, 2023 16:29:20, всего редактировалось 1 раз.
The main features of the USI are: • Two-wire Synchronous Data Transfer (Master or Slave, fSCLmax = fCK/16) • Three-wire Synchronous Data Transfer (Master, fSCKmax = fCK/2, Slave fSCKmax = fCK/4)
Если учесть, что 4-битный счетчик работает по обоим фронтам входного сигнала, то и "неправильное" прерывание, при завышенной частоте вполне вероятно. Увидел ваше дополнение. Проблема решена?
На мастере clock rate = fck/16, а как на слейве это настроить непонятно.
Здесь надо под приемник подстраиваться. Attiny2313 у вас на 8МГц работает без делителя? Значит частота обмена должна быть не более 2МГц для 2 проводного или 500КГц для трехпроводного соединений.
Частота по линии SCK 32.5 кГц, SS 1 кГц, MOSI 4 кГц. Так же в протеусе подключил SPI DEBUGGER и окончательно убедился что мастер все правильно передает. Частота тактирования аттини и атмеги - 8 МГц.
Добавлено after 15 minutes 30 seconds: Сделал скриншот терминала SPI Debuger'а, там все верно: 1 байт - номер генератора(2), 2- байт частота в хексадермальном формате А7(1Гц- это 167), остальные байты нули.
Обана! Интрига становится все интереснее. Появились уже 2!! значимых байта, что, в принципе-то и правильно. Но и вопросы появились: 1. Что такое "остальные байты"? Откуда берутся и зачем вообще нужны? 2. Как и где в коде приемника обрабатывается первый байт и как приемник "понимает" - где какой?
Обана! Интрига становится все интереснее. Появились уже 2!! значимых байта, что, в принципе-то и правильно. Но и вопросы появились: 1. Что такое "остальные байты"? Откуда берутся и зачем вообще нужны? 2. Как и где в коде приемника обрабатывается первый байт и как приемник "понимает" - где какой?
1. Мастер передает 4 байта информации по SPI: 1 байт-номер генератора, он отвечает за то на какой ножке слейва будет генерироваться чатота, это значение подставляется в переменную nG, 3 остальных байта - численное значение частоты в хексадермальном формате, умноженное на число 167.
2. В прерывании USI_OVERFLOW, они передаются последовательно и записываются в объединение dFi, а потом подставляются в переменные nG(номер выходного пина) и fG(частота), а эти переменные подставляются в функции расчета регистра прерываний Таймера1 OCR1A(частота) и в само прерывание Таймера1(номер выходной ножки). Спойлер
Код:
typedef union { unsigned long int w ; // w as WORD unsigned int h[2]; // h as HALF-WORD unsigned char b[4]; // b as BYTE } Union32; Union32 dFi; void SpiSlaveInit() { #asm("cli") USICR = ((1<<USIWM0)|(1<<USICS1)); // Activate 3- Wire Mode and use of external clock but NOT the interrupt at the Counter overflow (USIOIE) PORTD |= 1<<CS; // Activate Pull-Up resistor on PD3 GIMSK |= 1<<INT1; MCUCR |= 1<<ISC10; #asm("sei") }
// If edge is falling, the command and index variables shall be initialized // and the 4-bit overflow counter of the USI communication shall be activated: reqID = 0; index = 0; flag_RT = 0; USICR |= (1<<USIOIE); USISR = 1<<USIOIF; // Clear Overflow bit } else{ // If edge is rising, turn the 4-bit overflow interrupt off: USICR &= ~(1<<USIOIE); } }
interrupt [USI_OVERFLOW] void usi_ovf_isr(void) { switch(reqID) { case 0: ch_num = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; break; case 1: dFi.b[0] = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; break; case 2: dFi.b[1] = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; break; case 3: dFi.b[2] = USIDR; USISR = 1<<USIOIF; // Clear Overflow bit reqID++; flag_RT = 1; break; } } void main(void) { static unsigned int fG_old = 0; SpiSlaveInit(); Tim1Init(); UpdateTim1A(fG);
#asm("sei") for(;;) { if (flag_RT = 1) { if (fG_old != fG) { //old value detction SetUpTim1A(fG); fG_old = fG; } nG= ch_num; //generator number fG= dFi.b[0]+dFi.b[1]+dFi.b[2]; //generator frequency set_out_pin (nG); SetUpTim1A(fG); } } }
Решил проверить кейсы светодиодиками и это дало результаты, в прерываниях инт1 они горят и 1 и 2 кейсы тоже, но 3 и 4 кейс не горят, значит они не работают. Теперь вопрос в том почему они не работают. Спойлер
Код:
interrupt [EXT_INT1] void ext_int1_isr(void) {
if((PIND & (1<<CS))== 0){ PORTD |= (1<<5); //зажечь д5 // If edge is falling, the command and index variables shall be initialized // and the 4-bit overflow counter of the USI communication shall be activated: reqID = 0; index = 0; flag_RT = 0; USICR |= (1<<USIOIE); USISR = 1<<USIOIF; // Clear Overflow bit } else{ // If edge is rising, turn the 4-bit overflow interrupt off: USICR &= ~(1<<USIOIE); PORTD |= (1<<6); //д6 } }
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения