Доброго времени суток, уважаемые коллеги!
Волею судеб, так сказать, перешёл от AVR и 51-х к MSP430 и вот уже три дня бьюсь с UART на MSP430F2132. Почитал форум, использовал примеры, но всё напрасно. Короче, помогите. Итак: пишу программу в ИАР 5.10.1, запускаю в Протеусе 7.7, пробовал и в железе. Частота кварца 7372800Hz, хочу получить битрейд 9600. Вот код:
#include "msp430x21x2.h"
#define RX_BUFFER_SIZE 24
unsigned char rx_buffer[RX_BUFFER_SIZE];
unsigned char rx_wr_index=0,rx_rd_index=0;
volatile unsigned char rx_counter=0;
unsigned char rx_buffer_overflow=0;
unsigned char i, b, command, ks, valid, addr[2], dat[16];
unsigned char *pdat = dat;
void pins_init(void){
P1DIR=0xFF;
P1OUT=0x11;
}
void osc_init(void){
BCSCTL1 |= XTS; // ACLK = LFXT1 = HF XTAL
BCSCTL3 |= LFXT1S1; // 3 – 16MHz crystal or resonator
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
}
while (IFG1 & OFIFG); // OSCFault flag still set?
BCSCTL2 |= SELM_3 + SELS; // MCLK = SMCLK = LFXT1 (safe)
}
void uart_init(void){
P3DIR |= BIT4;
P3SEL = 0x30;
UCA0CTL1 |= UCSSEL_3; // SMCLK
//UCA0CTL0 = UCMSB;
UCA0BR0 = 0x00; // 7372800Hz/9600 = 0x0300
UCA0BR1 = 0x03;
UCA0MCTL = 0; // Modulation UCBRSx = 0
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE;
}
unsigned char get(void)
{
unsigned char data;
//wdt_reset();
while(rx_counter==0){};
data=rx_buffer[rx_rd_index];
if(++rx_rd_index == RX_BUFFER_SIZE){
rx_rd_index=0;
}
__bic_SR_register(GIE);
--rx_counter;
__bis_SR_register(GIE);
return data;
}
void put(unsigned char data){
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = data;
}
void put0(unsigned char num){
for(i=0;i<num;i++)put(0);
}
unsigned char receivedata(void){
command=get(); //приняли команду 1 байт
// принимаем адрес 2 байта
for(i=0;i<2;i++){
addr[i]=get();
}
//вычисляем контрольную сумму и ...
b=0x55^command^addr[0]^addr[1];
// ... одновременно принимаем данные 16 байт
for(i=0;i<16;i++){
dat[i]=get();
b=b^dat[i];
}
ks=get();//приняли контрольную сумму
//далее проверка контрольной суммы
if(b!=ks){
// контрольная сумма некорректна
put(0x55);
put(0x41);
put(0x01);
put0(17);
put(0x15);
return 1;
}else return 0;
}
void main(void){
WDTCTL = WDTPW + WDTHOLD;
pins_init();
osc_init();
uart_init();
__bis_SR_register(GIE);
while(1){
b=get();
if(b==0x55){ //нашли метку во входной информации, далее принимаем все 20 байтов
receivedata();
//основной процесс обработки и выполнения команд
if(command==0x10){
//case 0x10:
// проверяем валидность ключевой комбинации
valid=1;
if(addr[0]!=0x12)valid=0;
if(addr[1]!=0x34)valid=0;
if(valid){
put(0x55);
put(0x41);
put(0x02);
put0(17);
put(0x16);
}else{
put(0x55);
put(0x41);
put(0x03);
put0(17);
put(0x17);
}
}
}
}
}
// USCI A0/B0 Receive ISR
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if(!(UCA0STAT & UCRXERR))
{
rx_buffer[rx_wr_index]=UCA0RXBUF;
if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
}
}
}
Кидаю по ком-порту последовательность 55.10.12.34.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.63, получаю через раз C5. Почему так? Что не правильно? В протеусе все частоты (MCLK, SMCLK, ACLK выставил равными кварцевой частоте).