Я очень старался заставить шину SPI работать на DSPIC33EP128GM604. Я настроил SPI3 как стандартный 8-битный мастер-модуль и назначил контакт выбора микросхемы, чтобы я мог переключать ведомые устройства.
Я не могу заставить линию выбора микросхемы работать должным образом, кажется, что DSPIC не ожидает завершения передачи, прежде чем переключать линию выбора микросхемы с LOW на HIGH. Я проверил опечатки, и ничего не имеет отношения к этой проблеме. Кроме того, я попытался переключить линию CS на другой контакт. Я также пробовал модуль SPI 1, но проблема не устранена.
Вот мой код:
Конфигурация SPI 3:
void Init_SPI3 ( void )
{
IFS5bits.SPI3IF = 0; // Clear the Interrupt flag
IEC5bits.SPI3IE = 0; // Disable the interrupt
// SPI1CON1 Register Settings
SPI3CON1bits.DISSCK = 0; // Internal serial clock is enabled
SPI3CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI3CON1bits.MODE16 = 0; // Communication is word-wide (16 bits)
SPI3CON1bits.SSEN = 0; //No CS
SPI3CON1bits.MSTEN = 1; // Master mode disabled
SPI3CON1bits.PPRE = 2; //Pre-scaler
SPI3CON1bits.SPRE = 8;//Pre-scaler 2
SPI3CON1bits.SMP =1; // Input data is sampled at the middle of data output time
SPI3CON1bits.CKE =0; // Serial output data changes on transition from
SPI3CON1bits.CKP = 0; // Idle state for clock is a low level;
SPI3STATbits.SPIEN = 1; // Enable SPI module
// Interrupt Controller Settings
IFS5bits.SPI3IF = 0; // Clear the Interrupt flag
IEC5bits.SPI3IE = 1; // Enable the interrupt
}
Конфигурация 3-контактного SPI:
TRISBbits.TRISB10 = 0; //Set SPI3CLK as output
TRISBbits.TRISB11 = 0; //Set SPI3DATAOUT as output
RPOR4bits.RP42R=32; //SPI3_CLK out
RPOR4bits.RP43R=31; //SPI3_DATA out
Конфигурация выводов линии выбора чипа:
TRISBbits.TRISB4 = 0; //SPI3 CS is on Pin B4, set it to Output
Простая основная процедура:
while(1==1){
PORTBbits.RB4 = 0;//Set CS line to low
WriteSPI3(0xaa); //This is from the peripheral library to be safe....
PORTBbits.RB4 = 1; //Set CS line to high
}
Но вот вывод:
Судя по техническому описанию и примерным кодам, флага приемного буфера достаточно, чтобы сообщить нам, когда событие TX завершено, и, таким образом, CS может переключиться. Немного странно, почему для этого чипа нет флага, сообщающего нам, когда регистр сдвига SPI передал все свои данные. Весь код примера проверяет только флаг буфера приема.
После долгих размышлений, проб и ошибок и, наконец, форумов по микрочипам я могу подтвердить, что этот код работает :
uint8_t Write_SPI1(uint8_t command) { //Does work
SPI1BUF = command; // send data over SPI
while(!SPI1STATbits.SPIRBF) ; //wait until SPIRBF goes high
return SPI1BUF; //KEY STATEMENT THAT MADE A DIFFERENCE, Return the actual data received
}
Наряду с этим кодом, если ваше периферийное устройство зависит от выбора периферийного контакта (SPI2, SPI3 и т. д.), важно определить не только SPI Clock Out, но и SPI Clock In, даже если вы находитесь в ведущем режиме .
Однако меня сбивает с толку то, что этот код (который, я думаю, должен делать то же самое) не работает:
void Write_SPI1(uint8_t command) { //Does not work, premature toggle of CS, tried this code initially....
uint8_t garbage;
SPI1BUF = command; // send data over SPI
while(!SPI1STATbits.SPIRBF) ; //wait until SPIRBF goes high
garbage = SPI1BUF; // read dummy data, does not seem to clear the flag as expected
}
Подождите, пока передача SPI не будет завершена, прежде чем отменить выбор чипа с помощью чего-то вроде
while(SPI3_Tx_Buf_Full); //wait till completion of transmission
См. пример использования SPI1 по адресу http://pat.cybersites.ca/docs/PIC24F/SPI_Example1.html .
while(SPI3STATbits.SPITBF){};
не имеет значения, модуль каким-то образом неправильно устанавливает флаг?SPITBF
указывает только на то, есть ли биты в буфере, а не на то, идет ли передача. После того, как while
вы добавили оператор, попробуйте while(!SPI3STATbits.SPIRBF)
удерживать, пока передача не будет завершена и что-то не будет помещено в буфер приема (даже если вы ничего с этим не делаете).SPI3_Tx_Buf_Full
должен быть макрос, проверяющий правильный бит. Вы сами утверждаете CS с помощью PORTBbits.RB4 = 0
, поэтому вы также должны сами его отменить. Вам просто нужно дождаться, пока периферийное устройство закончит смещение битов. Если бы библиотека делала это сама ПОСЛЕ запуска передачи, это просто тратило бы впустую циклы ЦП, которые вы, возможно, захотите использовать каким-то другим способом. Может быть встроенная проверка перед записью следующего значения внутрь WriteSPI3
. Но это до запуска периферии, а не послеwhile(!SPI3STATbits.SPIRBF)
: Никаких изменений, за исключением того факта, что CS поддерживается немного дольше, и я получаю только одну передачу, после которой Pic ничего не делает, поэтому он явно зацикливается на этом операторе while.void __attribute__((interrupt,auto_psv)) _SPI3Interrupt(void) { PORTBbits.RB4 = 1; }
и установил .SISEL на 5. Все еще никаких изменений. Я начинаю думать, что это возможная ошибка?void Write_SPI1 ( int16_t command ) { int16_t temp; PORTBbits.RB7 = 0; // lower the slave select line temp = SPI1BUF; // dummy read of the SPI1BUF register to clear the SPIRBF flag SPI1BUF = command; // write the data out to the SPI peripheral while( !SPI1STATbits.SPITBF ) // wait for the data to be sent out ; PORTBbits.RB7 = 1; // raise the slave select line }
void Write_SPI2 ( int16_t command ) { int16_t temp; PORTBbits.RB6 = 0; // lower the slave select line temp = SPI1BUF; // dummy read of the SPI1BUF register to clear the SPIRBF flag SPI1BUF = command; // write the data out to the SPI peripheral while( !SPI1STATbits.SPIRBF ) // wait for the data to be sent out ; PORTBbits.RB6 = 1; // raise the slave select line }
Скотт Сейдман
Скотт Сейдман
МАМ
Скотт Сейдман
МАМ
Скотт Сейдман
Марко ван де Воорт