Дано:
- MSP430FG4618/F2013 Experimenter Board(в документации на плату присутствует схема электрическая принципиальная);
- Необходимость передать данные по SPI с MSP430F2013(master, USI) в MSP430FG4618(slave, USCI);
Суть проблемы:
При замере осциллографом уровней на выходе MasterOut(F2013), они оказываються слишком низкими (1 В), при этом уровни сигнала CLK достаточно высоки (3В). В режиме холостого хода(с разомкнутыми перемычками, которые связывают интерфейсы USI и USCI двух контроллеров ) на выходе микросхемы F2013 уровни нормальные(тоже приблизительно 3В). Почитав доки, товарищ узнал, что для этих микросхем -- уровень переключения с 0 в 1 -- 1,5 В. Т.е. уровень слишком низкий. Прерывания по приему генерируються. В буффере 0.
Хоть мне кажеться, что, возможно, проблема не в коде, но все же:
Программа для F2013
Код
#include <msp430x20x3.h>
#include "intrinsics.h"
// Prototypes
void init_spi(void);
void init_clocking(void);
void send_data(char data);
//EOF Prototypes
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
init_spi();
init_clocking(void);
__enable_interrupt();
int i;
while(1){
send_data(0xAA);
for(i=0;i<10000;i++);
}
}
void init_spi(void){
USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; // Port, SPI master
// USICTL1 |= USIIE; // Counter interrupt, flag remains set
USICKCTL = USIDIV_7 + USISSEL_2; // /128 SMCLK
USICTL0 &= ~USISWRST;
}
void init_clocking(void){
/* Use the VLOCLK oscillator. This is important. If we leave the unused 32kHz
oscillator running, its pins will not be free for sensing. */
BCSCTL3 = LFXT1S_2;
BCSCTL1 = CALBC1_16MHZ; /* Set the DCO speed */
DCOCTL = CALDCO_16MHZ;
/* We must turn off the low frequency crystal oscillator, as we are using its pins as I/O pins */
_BIS_SR(OSCOFF);
return;
}
void send_data(char data){
USISRL = data;
USICNT = 8;
while(!(USICTL1 & USIIFG));
return;
}
#include "intrinsics.h"
// Prototypes
void init_spi(void);
void init_clocking(void);
void send_data(char data);
//EOF Prototypes
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
init_spi();
init_clocking(void);
__enable_interrupt();
int i;
while(1){
send_data(0xAA);
for(i=0;i<10000;i++);
}
}
void init_spi(void){
USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; // Port, SPI master
// USICTL1 |= USIIE; // Counter interrupt, flag remains set
USICKCTL = USIDIV_7 + USISSEL_2; // /128 SMCLK
USICTL0 &= ~USISWRST;
}
void init_clocking(void){
/* Use the VLOCLK oscillator. This is important. If we leave the unused 32kHz
oscillator running, its pins will not be free for sensing. */
BCSCTL3 = LFXT1S_2;
BCSCTL1 = CALBC1_16MHZ; /* Set the DCO speed */
DCOCTL = CALDCO_16MHZ;
/* We must turn off the low frequency crystal oscillator, as we are using its pins as I/O pins */
_BIS_SR(OSCOFF);
return;
}
void send_data(char data){
USISRL = data;
USICNT = 8;
while(!(USICTL1 & USIIFG));
return;
}
Программа для FG4618
Код
#include "msp430xG46x.h"
#include "intrinsics.h"
#define ARROWS LCDM11
#define UP 0x10
#define DOWN 0x40
void init_LCD(void);
void init_SPI(void);
__interrupt void SPI_int(void);
char SPI_ARROW;
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
SCFQCTL = SCFQ_4M;
SCFI0 = 0x08;
FLL_CTL1 |= SELS;
init_LCD();
init_SPI();
ARROWS = DOWN; //Test
__enable_interrupt();
while(1);
}
void init_LCD(void){//Сюда можно не смотреть, это вывод на LCD
/*Enable peripherial port functionality*/
P5SEL = BIT2 + BIT3 + BIT4;
P5DIR = BIT2 + BIT3 + BIT4;
LCDACTL |= LCDFREQ1;
LCDACTL |= LCDFREQ0;
/*4x MUX*/
LCDACTL|=LCDMX1;
LCDACTL|=LCDMX0;
/*LCD segments enabled*/
LCDACTL|=LCDSON;
/*Turn LCD on*/
LCDACTL|=LCDON;
/*Enable arrows*/
LCDAPCTL1 = 0x00;
LCDAPCTL0 = LCDS20;
/*Charge pump voltage select*/
LCDAVCTL1 = VLCD0; //2.6V
LCDAVCTL0 = LCDCPEN;
LCDM12 = 0x00;
return;
}
void init_SPI(void){
//slave SPI
P3SEL = 0x0E; // P3.3,2,1 option select
UCB0CTL1 = UCSWRST; // **Put state machine in reset**
UCB0CTL0 = UCSYNC+UCMSB; // 3-pin, 8-bit SPI master
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCB0RXIE; // Enable USCI_B0 RX interrupt
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void SPI_int(void){
SPI_ARROW = UCB0RXBUF;
ARROWS = 0;
if(SPI_ARROW == 0x00)
ARROWS = UP;
else
ARROWS = DOWN;
//Clear interrupt flag
//IFG2&=~UCB0RXIFG;
return;
}
#include "intrinsics.h"
#define ARROWS LCDM11
#define UP 0x10
#define DOWN 0x40
void init_LCD(void);
void init_SPI(void);
__interrupt void SPI_int(void);
char SPI_ARROW;
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
SCFQCTL = SCFQ_4M;
SCFI0 = 0x08;
FLL_CTL1 |= SELS;
init_LCD();
init_SPI();
ARROWS = DOWN; //Test
__enable_interrupt();
while(1);
}
void init_LCD(void){//Сюда можно не смотреть, это вывод на LCD
/*Enable peripherial port functionality*/
P5SEL = BIT2 + BIT3 + BIT4;
P5DIR = BIT2 + BIT3 + BIT4;
LCDACTL |= LCDFREQ1;
LCDACTL |= LCDFREQ0;
/*4x MUX*/
LCDACTL|=LCDMX1;
LCDACTL|=LCDMX0;
/*LCD segments enabled*/
LCDACTL|=LCDSON;
/*Turn LCD on*/
LCDACTL|=LCDON;
/*Enable arrows*/
LCDAPCTL1 = 0x00;
LCDAPCTL0 = LCDS20;
/*Charge pump voltage select*/
LCDAVCTL1 = VLCD0; //2.6V
LCDAVCTL0 = LCDCPEN;
LCDM12 = 0x00;
return;
}
void init_SPI(void){
//slave SPI
P3SEL = 0x0E; // P3.3,2,1 option select
UCB0CTL1 = UCSWRST; // **Put state machine in reset**
UCB0CTL0 = UCSYNC+UCMSB; // 3-pin, 8-bit SPI master
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCB0RXIE; // Enable USCI_B0 RX interrupt
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void SPI_int(void){
SPI_ARROW = UCB0RXBUF;
ARROWS = 0;
if(SPI_ARROW == 0x00)
ARROWS = UP;
else
ARROWS = DOWN;
//Clear interrupt flag
//IFG2&=~UCB0RXIFG;
return;
}
Буду рад помощи