Код
//******************************************************************************
// Инициализация SPI интерфейса
//******************************************************************************
void SPI_Setup(void)
{
DCO_Init(); // Инициализация генератора
DIO_Init(); // Инициализация портов ввода/вывода
// Инициализация режима работы SPI
UCB1CTL1 |= UCSWRST;
UCB1CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB1CTL1 |= UCSSEL_2; // SMCLK
UCB1BR0 |= 0x02; // BRCLK = SMCLK/2
UCB1BR1 = 0; //
UCB1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UC1IE |= UCB1RXIE | UCB1TXIE; // Enable USCI1 RX interrupt
__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
// задержка 15 мс
__delay_cycles(15000);
}
// Инициализация SPI интерфейса
//******************************************************************************
void SPI_Setup(void)
{
DCO_Init(); // Инициализация генератора
DIO_Init(); // Инициализация портов ввода/вывода
// Инициализация режима работы SPI
UCB1CTL1 |= UCSWRST;
UCB1CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
UCB1CTL1 |= UCSSEL_2; // SMCLK
UCB1BR0 |= 0x02; // BRCLK = SMCLK/2
UCB1BR1 = 0; //
UCB1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UC1IE |= UCB1RXIE | UCB1TXIE; // Enable USCI1 RX interrupt
__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
// задержка 15 мс
__delay_cycles(15000);
}
Привожу функцию DCO_Init();
Код
//******************************************************************************
// DIO_INIT(): функция инициализации внутреннего генератора
//******************************************************************************
void DCO_Init(void)
{
volatile unsigned int i;
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
{
while(1); // If calibration constants erased
// do not load, trap CPU!!
}
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
for(i=2100;i>0;i--); // Wait for DCO to stabilize.
}
// DIO_INIT(): функция инициализации внутреннего генератора
//******************************************************************************
void DCO_Init(void)
{
volatile unsigned int i;
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
{
while(1); // If calibration constants erased
// do not load, trap CPU!!
}
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
for(i=2100;i>0;i--); // Wait for DCO to stabilize.
}
И еще одна функция, функция чтения значения регистра из вокодера
Код
//******************************************************************************
// SPI_ReadReg(): считывает 8-и битное значение из регистра с адрессом (addr).
// Полученное значениеэтого регистра записывается в переменную x
//******************************************************************************
char SPI_ReadReg_8(char addr)
{
char x; // Переменная в которой хранится значение
// регистра
P5OUT &= ~CSN; // Выбор CMX618
//делаем задержки примерно 3 мкс
__no_operation();
__no_operation();
__no_operation();
while (!(UC1IFG & UCB1TXIFG)); // Ждем пока TX буфер не освободиться
UCB1TXBUF = addr; // Записываем в TX буфер адресс
while (!(UC1IFG & UCB1TXIFG)); // Ждем пока TX буфер не освободиться
UCB1TXBUF = 0; // Делаем ложную передачу, одновременно
// принимаем значение из нужного регистра
//while (!(UCB1STAT & UCBUSY)); // Ждем пока операция приема/передачи не
// закончится
while (!(UC1IFG & UCB1RXIFG));
x = UCB1RXBUF; // Записываем в переменную x принятое
// значение регистра
P5OUT |= CSN; // Отключаем CMX618
return x; // Возвращаем x
}
// SPI_ReadReg(): считывает 8-и битное значение из регистра с адрессом (addr).
// Полученное значениеэтого регистра записывается в переменную x
//******************************************************************************
char SPI_ReadReg_8(char addr)
{
char x; // Переменная в которой хранится значение
// регистра
P5OUT &= ~CSN; // Выбор CMX618
//делаем задержки примерно 3 мкс
__no_operation();
__no_operation();
__no_operation();
while (!(UC1IFG & UCB1TXIFG)); // Ждем пока TX буфер не освободиться
UCB1TXBUF = addr; // Записываем в TX буфер адресс
while (!(UC1IFG & UCB1TXIFG)); // Ждем пока TX буфер не освободиться
UCB1TXBUF = 0; // Делаем ложную передачу, одновременно
// принимаем значение из нужного регистра
//while (!(UCB1STAT & UCBUSY)); // Ждем пока операция приема/передачи не
// закончится
while (!(UC1IFG & UCB1RXIFG));
x = UCB1RXBUF; // Записываем в переменную x принятое
// значение регистра
P5OUT |= CSN; // Отключаем CMX618
return x; // Возвращаем x
}
Теперь несколько вопросов:
1. Для примера сделал программу
Код
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Остановка сторожевого таймера
static char value;
SPI_Setup();
value = SPI_ReadReg_8(MVCFG);
while(1)
{}
}
{
WDTCTL = WDTPW + WDTHOLD; // Остановка сторожевого таймера
static char value;
SPI_Setup();
value = SPI_ReadReg_8(MVCFG);
while(1)
{}
}
Программа зацикливается когда вызывается функция DCO_Init(), а именно на строчке
Код
for(i=2100;i>0;i--); // Wait for DCO to stabilize.
Получается что генератор не стабилизируется? (Эту настройку генератора я взял из примера, поэтому не пойму что она делает.)
2. Если я убираю строку
Код
__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
то программа не "подвисает" на цикле for. Но естественно не работае SPI. Так как прерывания отключены.
3. Объясните пожалуйста когда появляется сигнал тактирования на ножке CLK и смогу ли посмотреть его на осциллографе?. Сигнал появляется когда я дергаю CSN в ноль или когда записываю в буфер передатчика UCB1TXBUF данные?