Обсуждаем контроллеры компании Atmel.
Пт июн 09, 2023 14:54:10
Дайте ориг. код откуда взяли пример для:
- Код:
dFi.w = F*167.77216; //частота передаваемая через SPI, какое-то фиксированное число 167.77216
PORTB &= ~_BV(PB0);
SPI_MasterTransmit(Cnt & 0x03);//0x03-маска
SPI_MasterTransmit(dFi.b[0]);//флаги передачи
SPI_MasterTransmit(dFi.b[1]);//флаги передачи
SPI_MasterTransmit(dFi.b[2]);//флаги передачи
Боюсь, что dFi.w не dFi.w, a &Fi.w (указатель, а [0], [1] ... - индекс для ячейки для double переменных.
Иначе я без побитового сдвига понятия не имею, как можно получить частоту в 3 байта, тем более со десет. знаком (F*167.77216).
А и какой double, в Вашем компиляторе для этого МК вероятно double -> float (32 bit).
Портировать код с другого МК на этот?
Последний раз редактировалось
veso74 Пт июн 09, 2023 15:03:36, всего редактировалось 4 раз(а).
Пт июн 09, 2023 15:01:25
Начал менять настройки мастера, изменил прескейлер в регистре SPI SPCR с 16 до 128, при частоте CK - 7813 Гц и заработал 3 кейс.
MOHCTEP был прав, осталось разобраться с как настроить частоту, чтобы работали все 4 кейса USI_OVERFLOW. Но пока что ка как бы я не настраивал частоту мастера, 4 кейс оживить не удается.
Добавлено after 2 minutes 33 seconds:veso74, это прошивка с рабочего прибора, прошивка с слейва не сохранилась и сгорела в результате КЗ.
Скинул архив, иницилизация SPI в USART.c. Слейв в данной ситуации выступает как регулируемый генератор меандра.
- Вложения
-
- KD8105.rar
- (511.15 KiB) Скачиваний: 23
Пт июн 09, 2023 15:41:54
warptred12, Попробуйте такой вариант сброса reqID.
- Код:
switch(reqID) {
...
...
case 3:
dFi.b[2] = USIDR;
USISR = 1<<USIOIF; // Clear Overflow bit
reqID++; // !!
flag_RT = 1;
break;
}
reqID %=4;
...
Пт июн 09, 2023 15:58:21
После некоторых изменений, таких как перенос из for функции инициилизации USI и изменения прескейлера частоты тактирующего сигнала мастера, МК в протеусе начал реагировать на измения номера ножки и частоты со стороны мастера. Теперь 1 байт(номер ножки, отправляемый со стороны мастера) определяется корректно и на заданной ножке генерируется частота, но частота не соответствует заданной и форма генерируемой частоты далека от меандра.
Я думаю, что это связано с тем что кейс 3 по прежнему не работает, также пробовал подавать 2-х байтные и 1-байтные числа по SPI со стороны мастера и все равно частота на выходе МК ATtiny2313 не корректна.
На данный момент присутствует 3 основные проблемы:
1) Неверная частота на выходе МК.
2) Неверная форма сигнала, должен быть меандр.
3) Хоть и частота генерируется на верной ножке, почему-то МК подает +5В на другие ножки, которые задействованы как выводы частоты nG, а этого быть не должно.
Вот актуальный код слейва:
Добавлено after 4 minutes 15 seconds:MOHCTEP, этот вариант сброса не помогает, просто появляется +5В на ножках PB0 и PB1.
Добавлено after 5 minutes 5 seconds:Вот форма генерируемого сигнала.
- Вложения
-
- Безымянный4.pdf
- (601.27 KiB) Скачиваний: 29
Пт июн 09, 2023 16:11:48
VFG_DDR тоже настройте один раз, при инициализации. Тогда set_out_pin (nG); будет не нужна. Вместо ее вызова, в бесконечном цикле достаточно будет строки nG=1<<ch_num;
Пт июн 09, 2023 16:27:12
MOHCTEP, тогда при nG = 0 на мастере(0x00000000), частота генерируется на ножках PB0 и PB1.
Добавлено after 3 minutes 50 seconds:При nG = 1(0x00000001), частота генерируется на ножке PB1, при nG = 2(0x00000002), частота генерируется на ножке PB2.
- Вложения
-
- Безымянный5.pdf
- (620.77 KiB) Скачиваний: 23
Пт июн 09, 2023 16:38:04
nG никогда не должно быть == 0. При ch_num ==0, nG ==1.
- Код:
void main(void)
{
static unsigned int fG_old = 0;
unsigned long int tmp;
Tim1Init();
UpdateTim1A(fG);
SpiSlaveInit();
//DDRA=0b11111111;
DDRB=0b11111111;
DDRD=0b11110111;
#asm("sei")
for(;;) {
//delay_ms(1);
PORTD &= (~((1<<0)|(1<<1)|(1<<2)|(1<<4)|(1<<5)|(1<<6)));
//PORTB &= (~(1<<3)|(1<<4)|(1<<6));
//PORTA &= (~(1<<0)|(1<<1));
if (fG_old != fG) { //old value detction
SetUpTim1A(fG);
fG_old = fG;
}
nG=1<<ch_num; //generator number
fG = dFi.b[1] << 8;
tmp = dFi.b[2] << 16;
fG |= tmp;
tmp = dFi.b[2] << 24;
fG |= tmp; //generator frequency
//set_out_pin (nG);
SetUpTim1A(fG);
}
}
Как-то так...
Пт июн 09, 2023 17:11:00
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;
объединение - каждый элемент (w,h,b) начинается с одной и тойже ячейки памяти,
т.е. dFi.b[0] - это младший байт из dFi.w
dFi.w = F*167.77216; - здесь неявное преобразование float->long int
(как компилятор это делает я не знаю, допустимо ли выбрасывать старший байт)
в передаче:
SPI_MasterTransmit(Cnt & 0x03); //1-й байт
SPI_MasterTransmit(dFi.b[0]); //2-байт - младший из dFi.w
SPI_MasterTransmit(dFi.b[1]); //3-байт - второй из dFi.w
SPI_MasterTransmit(dFi.b[2]); //4-байт - третий из dFi.w,
четвертый из dFi.w - проигнорирован, не передается,
т.е. целостность unsigned long int w нарушается
при приеме:
ch_num = USIDR;
dFi.b[1] = USIDR; - младший из dFi.w
dFi.b[2] = USIDR; - второй из dFi.w
dFi.b[3] = USIDR; - третий из dFi.w
fG = dFi.b[1] << 8;
tmp = dFi.b[2] << 16;
fG |= tmp;
tmp = dFi.b[2] << 24;
fG |= tmp;
т.е. в fG <b[1]><b[1]><b[0]>< 00 > (здесь b[] - из dFi.w передатчика)
а в dFi.w <b[3]><b[2]><b[1]><b[0]>
Добавлено after 11 minutes 45 seconds:
а между тем, если б передавать 5 байт (номер, float)
результат вычисления переправлялся бы целёхоньким
dFi.f = F*167.77216; - без преобразования типа
typedef union
{
float f;
unsigned long int w ; // w as WORD
unsigned int h[2]; // h as HALF-WORD
unsigned char b[4]; // b as BYTE
} Union32;
SPI_MasterTransmit(Cnt & 0x03); //1-й байт
SPI_MasterTransmit(dFi.b[0]); //2-байт - младший из dFi.f
SPI_MasterTransmit(dFi.b[1]); //3-байт - второй из dFi.f
SPI_MasterTransmit(dFi.b[2]); //4-байт - третий из dFi.f
SPI_MasterTransmit(dFi.b[3]); //5-байт - четвертый из dFi.f
и ничего не надо ручками склеивать в приемнике dFi.f = dFi.f передатчика, он же fG
Пт июн 09, 2023 17:14:39
...
dFi.w = F*167.77216; - здесь неявное преобразование float->long int
...
- Код:
dFi.w = (unsigned long int)((float)F * 167.77216);
На одном компиляторе так должно быть, с другой - получилось и в оригинале.
Пт июн 09, 2023 17:31:21
a797945, а вот как этот 3 байт ловить не понятно, в прерывании программа не доходит до case 3. Вероятно отправляются 4 байта вместо 5 - для экономии памяти attiny.
Частота SCK задана минимальной на мастере(прескейлер 128/7813Гц). Не понимаю как мне подогнать Attiny под частоту тактирования мастера.
Пт июн 09, 2023 19:17:45
я не специалист, и тем паче не специалист по avr,
мне сложно Вам что-то советовать связанное со структурой МК или его перефирией.
если Вы предполагаете нехватку ресурсов на слейве, попробуйте
(для эксперимента) отправлять на слейв фиксированные "частоты", идея в том чтоб наладить передачу и генерацию, а математику со слейва пока убрать
эту:
for(i=0;i<=4;i++) {
TimDiv = (F_CPU/(2*(Foc/167.77216)*N[i])-1)+0.5;
if(TimDiv >= 0 && TimDiv<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
}
т.е. посчитать несколько значений для таймера(ов) слейва, мастером эти значения (через паузу или по кнопке) отсылать на слейв, там принимать и без математики просто записывать в таймер(а).
Вы все еще в протеусе или пробовали на "железе"?
Пт июн 09, 2023 19:20:45
a797945, ну ток с понедельника смогу в железе посмотреть, а пока в протеусе смотрю. Попробую этот вариант, отпишусь как будут результаты.
Пт июн 09, 2023 19:25:51
если задача не решается - всегда приходится разбивать ее на части, местами на небольшие - и отлаживать по частям
Вт июл 04, 2023 16:20:49
Проблема довольно сильно затянулась и до сих пор не удалось отладить в железе прошивку на attiny2313, так что я решил параллельно заниматься написанием прошивки на контроллер с полноценной поддержкой SPI ATMEGA8.
Код слейва:
Мне кажется этот код интуитивно более понятен и будет проще его отладить, хотябы в протеусе, чтобы были дополнительные варианты в случае неудачи с аттини.
Ну проблема в том, что программа записывает только первый байт информации(nG - выбор выходной ножки котроллера), а в остальные записывает нули, так что вопрос к экспертам, где я облажался?
Добавлено after 38 minutes 21 second:Теперь работает только PC0 и на нем частота 32 Гц, хотя ничего не менял в коде.
Вт июл 04, 2023 17:39:02
Непонятна суть цикла
- Код:
for (i = 0; i < sizeof(master_arr); i++) {
nG = master_arr[i]; //generator number
fG = master_arr[i] << 8;
tmp = master_arr[i] << 16;
fG |= tmp;
tmp = master_arr[i] << 24;
fG |= tmp;
//generator frequency
UpdateTim1A(fG);
SetUpTim1A(fG);
}
Здесь вы всегда манипулируете последним байтом массива master_arr, назначая его обеим переменным nG и fG.
Вт июл 04, 2023 17:51:48
MOHCTEP, первый полученный байт по SPI, я присваиваю значению массива master_arr[0], а это значение присваиваю переменной nG(номер выхода генератора), master_arr[1],master_arr[2],master_arr[3] я пытаюсь присвоить переменной fG(частота генератора, подставляемая в формулу расчета регистра OCR1A).
Идея такова, что каждое прерывание я записываю по байту информации в массив master_arr[i], а в основном цикле я пытаюсь присвоить эти значения переменным nG и fG. Ну такова была идея по крайней мере.
Добавлено after 3 minutes 21 second:
Функция for (i = 0; i < sizeof(master_arr); i++) нужна для того чтобы подставить эти значения в правильном порядке, но опят таки я не уверен что это работает правильно.
Вт июл 04, 2023 18:05:06
Нет. Вы циклом всегда присваиваете каждый байт массива, по очереди, обеим переменным сразу. В итоге, после отработки этого странного цикла, обеим переменным будет присвоен последний байт массива.
Уберите этот цикл и модифицируйте переменные обращаясь к массиву по числовым индексам master_arr[0],master_arr[1]... и master_arr[3](четвертый байт) вам недоступен, так как длина массивов у вас = 3 байтам.
Вт июл 04, 2023 18:44:17
MOHCTEP, я увеличил массив до 4, потому что по SPI передается 4 байта, так будет верно ?
Добавлено after 20 minutes 58 seconds:Ну результат все тот же, в принципе.
Добавлено after 8 minutes 53 seconds:Вопрос в том как это починить, чтобы оно работало или лучше писать заново.
Добавлено after 4 minutes 54 seconds:Если что пример кода для реализации SPI slave'a брал тут:
https://dzen.ru/media/esp32/spi-arduino ... adboard.ru
Вт июл 04, 2023 19:54:15
Ну... сложно что то умное подсказать на расстоянии, да еще и для протеуса. В качестве версии: проблема возможна в том, что вы постоянно перестраиваете переменные nG и fG в главном цикле и вместе с ними таймер. Независимо от того - пришло там что-то по SPI или нет. Возможно ваш таймер, от постоянных перенастроек, просто не успевает нормально отрабатывать цикл. Вот у вас есть счетчик заполнения массива countSPIb. Можно, к примеру, в майн цикле проверять его на равенство длине массива (это значит, что пришли все 5 байт от мастера и данные подготовлены) и только в этом случае пересчитать переменные + таймер и сбросить счетчик countSPIb, подготовившись к следующему приему.
Как-то так примерно...
- Код:
interrupt [SPI_STC] void spi_isr(void) // Прерывание SPI1 - пришел байт
{
if (countSPIb < 0) { // пришла "пустышка"
countSPIb++; // увеличивам счетчик
SPDR = slave_arr [countSPIb]; // подгружаем нулевой байт массива ведомого
PORTC |= (1<<0);
return; // выходим из процедуры
}
master_arr [countSPIb] = SPDR1; // получаем байт от мастера
countSPIb++; // увеличиваем счетчик
SPDR = slave_arr [countSPIb]; // отдаем байт ведомого (+1 индекс)
PORTC |= (1<<1);
if (countSPIb >= sizeof(master_arr)) { // если кончился массив
PORTC |= (1<<2);
//countSPIb = -1; // обнуляем счетчик и ждем следующий обмен
}
}
...
void main(void){
...
for(;;){
...
if (countSPIb >= sizeof(master_arr)){
nG = master_arr[0]; //generator number
fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24);
UpdateTim1A(fG);
SetUpTim1A(fG);
countSPIb = -1;
}
}
}
Ср июл 05, 2023 12:28:06
MOHCTEP, в протеусе мастер отправляет верные данные, в хексадермальном формате 02 5C 8F 02(первый байт номер генератора, остальные 3 значения частоты), а вот в ответ мастеру - слейв шлет 00 01 01 01 в ответ, это значит, что по какой-то причине, байты, полученные от мастера записываются в единицы. Если я правильно понимаю, как работает SPI, то при получении байта, слейв отправляет полученный байт мастеру, в неизмененном виде, а у меня не так получается. Это значит что скорее всего код в прерывании криво написан, но пока конкретно не ясно, что там не так.
Добавлено after 7 minutes 56 seconds:А для хранения значения переменной fg, у меня есть такая функция, которая сравнивает старое и новое значение и не изменилось ли значение fG
Добавлено after 4 minutes 34 seconds:Еще может быть проблема в том, чт переменная fG - 32-х битная(unsigned long int), а мы записываем в нее 24 бита. Но я даже не знаю как это проверить, просто предположение.
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.