Страница 1 из 1

Usart в Xmega

Добавлено: Пт июл 17, 2015 21:09:36
Nosaer
Здравствуйте)
Набросал не большой код:
UART настраивал на скорость в 9600 , 8 бит данных, 1 стоп бит и без бита парритета. Плюс отключен параметр удвоения скорости.

Код: Выделить всё

#define F_CPU 12000000UL
#define __DELAY_BACKWARD_COMPATIBLE__

#include <stdlib.h>
#include <avr/io.h>
#include <stdio.h>
#include <stddef.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

//Переменные
volatile char buf[26]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
volatile char dat[26]={0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};
unsigned char i,cnt,y;

// Функция включения USART_D1, cкорость 9600( а надо 250000) bod
void StartUsartD1()
{		
	USARTD1_BAUDCTRLB = 0;
    USARTD1_BAUDCTRLA = 0x4D; 
    USARTD1_CTRLA = 0;									//Отключение прерываний
    USARTD1_CTRLC = USART_CHSIZE_8BIT_gc;				//8 data bits, no parity and 1 stop bit
    USARTD1_CTRLB = USART_TXEN_bm | USART_RXEN_bm;		//Включение приема передатчика
	PORTD_OUTSET = PIN7_bm; 							//Настраиваем выводы PC6 и PC7
	PORTD_DIRSET = PIN7_bm; 
	PORTD_OUTCLR = PIN6_bm;
	PORTD_DIRCLR = PIN6_bm;
}
	
// Функция получения данных USART_D1.
char getChar1(void)
{
	char buffer1;	
	while (1)
		{
		while( !(USARTD1_STATUS & USART_RXCIF_bm) );
		buffer1=USARTD1_DATA;
		//if ((USARTD1_STATUS & (USART_BUFOVF_bm))==0)	
		if ((USARTD1_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0)
        return buffer1;
		};	
}

// Фунуция передачи данных USART_D1
void sendChar1(char d1)
{
	while( !(USARTD1_STATUS & USART_DREIF_bm) );
	USARTD1_DATA = d1;
}
 

// Функция инициализации 
int main(void)
{
	// Настройка работы от внешнего кварца в 12МГц
	cli();			
	OSC.XOSCCTRL = 0x8B;				
								
	OSC.CTRL = 0x08;										
	while((OSC.STATUS & 0x08) == 0);		
	
	//PORTD.OUTSET =0x04;	
	PORTD.DIR = 0x04;												
	
	//Активация USART
	StartUsartD1();
			
while (1)
      {
        cnt = getChar1();
        if (cnt ==0x55) {
						for (i=0;i<12;i++) sendChar1(buf[i]); 
                         
                       }   
        else           {                             
                          for (i=0;i<12;i++) sendChar1(dat[i]); }  
      };
}
Скомпилировал, прошил, запускаю терминал
По моей задумке если я отправляю 0x55(символ юникода получается U) то мне шлется массив с 0xFF, если что нить другое то 0x55.
В итоге две проблемы:
1) ответ идет в виде массива 0x0E, в теории говорит что скорость настроена не правильно. Но вроде перепроверил все.
Изображение

BSEL = 12000000/(2^0 * 16 * 9600) = 78.125 -1 = 77 (0x4D)
2) Как только прошил схему, без отправки контроллеру чего либо, он мне уже присылает в ответ 2 массива.

Помогите пожалуйста разобраться
Либо буду рад готовым рабочим примерам)

Re: Usart в Xmega

Добавлено: Чт июл 23, 2015 16:22:39
eess9
А вы уверены, что контроллер у вас реально работает от 12МГЦ, а не остался на внутренних 2МГц?

Код: Выделить всё

void MCU_Clock_init(void)
{
	/* Установка тактирования от 3-х кранной частоты внешнего генератора 3*16МГц=48МГц */
	OSC_XOSCCTRL = 0xCB;                  // выбор внешнего генератора с временем запуска 16 тыс. CLK и частотой 12-16 МГц
	OSC_CTRL = 0x08;                           // разрешение работы внешнего генератора
	while((OSC_STATUS & 0x08) == 0 ) ; // ожидание появления в регистре статуса бита включения синхронизации от внешнего генератора
	//OSC_PLLCTRL = 0xC3;                   // настройка блока PLL на синхронизацию от внешнего источника и 3-х кратоное умножение
	OSC_PLLCTRL = 0xC1;                   // настройка блока PLL на синхронизацию от внешнего источника и 1-х кратоное умножение
	OSC_CTRL = OSC_CTRL | 0x10;         // разрешение работы блока PLL
	while((OSC_STATUS & 0x10) == 0 ) ; // ожидание появления в регистре статуса бита включения блока PLL
	CCP = 0xD8;                                 // включение защиты от изменения регистров ввода-вывода на время изменения синхронизации
	CLK_CTRL = 0x04;                            // настройка системной синхронизации от блока PLL
	OSC_CTRL = OSC_CTRL & 0xFE;        // отключение системной синхронизации от внутреннего RC-генератора частотой 2 МГц
}
По uart гляньте это:

Код: Выделить всё

void USARTD1_init(void)  
{
	PORTD_DIR |= 0x80;//fot TxD USATRD1
	PORTD_OUT |= 0x80;
	
	//инициализация UART D1
	USARTD1_CTRLC = 0x0B;//2 стоповых бита
	USARTD1_BAUDCTRLA = 51;
	USARTD1_BAUDCTRLB = 0x10;          //  9600 bod, error: -0.08 %
	USARTD1_CTRLB = 0x18;//0x18;// Включить передатчик и приемник
	USARTD1_CTRLA = 0x30;// разрешаем прерывание по приему
}

Re: Usart в Xmega

Добавлено: Пт июл 24, 2015 14:51:17
Nosaer
Проблема с тактированием действительно была, и скорее всего все еще есть.

После добавления в код этих строк, контроллер перешел на более высокую частоту

Код: Выделить всё

CCP = CCP_IOREG_gc;
CLK.CTRL = CLK_SCLKSEL_XOSC_gc;	
Но связь настроилась не на 9600 bod, а на примерно 9400. Плюс бывают ошибки так как не на все мои посылки он отвечает.

В вашем примере вы включаете PLL и настраиваете его на однократное умножение. Получается, он просто синхронизируется так скажем по нему, но умножения частоты не происходит? И обязательно ли использование блока PLL?

Как доберусь до своего рабочего стола, обязательно опробую подправить под ваш код

Re: Usart в Xmega

Добавлено: Пт июл 24, 2015 15:08:44
eess9
PLL вроде бы не обязательна. Но вы должны четко понимать смысл этих картинок:
http://img.radiokot.ru/files/59180/thum ... 554vug.JPG
http://img.radiokot.ru/files/59180/medium/pmp56kmsk.JPG
Частота тактирования UART и ядра могут не совпадать! Посмотрите внимательно как у вас установлены предделители.

Re: Usart в Xmega

Добавлено: Пн июл 27, 2015 14:16:05
Nosaer
Программу переделал, нашел несколько ошибок, реализовал передачу данных по прерыванию.
Алгоритм работы в следующем, я шлю что угодно, мне приходит 0x55. Если я шлю символ юникода "U"(он же 0x55), то в ответ должно прийти 0x77.

Проблемы собственно такие:
1) На настроенную скорость в 9600 шлется полнейший мусор. Если ставлю в терминале скорость от 9500 bod и ниже, то ответ начинает приходить более реальный в виде массива 0x55. Но если если я начинаю слать "U", то в ответ жду массив 0x77. А он приходит 1 раз из 5-10, в остальных 4-9 случаях приходит зачем то массив 0x55.
2) Отвечает контроллер не на каждую мою посылку. То есть раз 5 щелкнешь отправить, а ответ придет только один раз.

Вот собственно последняя версия программы:

Код: Выделить всё

#define F_CPU 12000000UL

#include <stdlib.h>
#include <avr/io.h>
#include <stdio.h>
#include <stddef.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

volatile char buf[5]={0x77,0x77,0x77,0x77,0x77};
volatile char dat[5]={0x55,0x55,0x55,0x55,0x55};
unsigned char i,cnt,y;

void StartUsartD1()
{		
	USARTD1_CTRLC= USART_PMODE1_bm | USART_CHSIZE0_bm | USART_CHSIZE1_bm;
	USARTD1_BAUDCTRLB = 0;
    USARTD1_BAUDCTRLA = 0x47; //47 для 11,052 4D для 12 
	USARTD1_CTRLB = USART_TXEN_bm | USART_RXEN_bm;
	
	USARTD1_CTRLA=USART_RXCINTLVL0_bm;
	
	PORTD_OUTSET = PIN7_bm;
	PORTD_DIRSET = PIN7_bm; 
	PORTD_OUTCLR = PIN6_bm;
	PORTD_DIRCLR = PIN6_bm;
}
	
char getChar1(void)
{
	while(1){
	char buffer1;	
		buffer1=USARTD1_DATA;	
		//if ((USARTD1_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0)
        return buffer1;
	}			
}

void sendChar1(char d1)
{
	while( !(USARTD1_STATUS & USART_DREIF_bm) );
	USARTD1_DATA = d1;
}
 
ISR(USARTD1_RXC_vect)
{
	cnt = getChar1();	
}	

int main(void)
{
// Clock Source Select
	OSC.XOSCCTRL = 0x8B;			 // выбор внешнего генератора с временем запуска 16 тыс. CLK и частотой 8-12 МГц									
	OSC.CTRL = 0x08;			     // разрешение работы внешнего генератора							
	while((OSC.STATUS & 0x08) == 0); // ожидание появления в регистре статуса бита включения синхронизации от внешнего генератора
	OSC_PLLCTRL = 0xC1;                // настройка блока PLL на синхронизацию от внешнего источника и 1-х кратоное умножение
	OSC_CTRL = OSC_CTRL | 0x10;        // разрешение работы блока PLL
	while((OSC_STATUS & 0x10) == 0 ) ; // ожидание появления в регистре статуса бита включения блока PLL
   	CCP = CCP_IOREG_gc;
    CLK.CTRL = CLK_SCLKSEL_XOSC_gc;	
	OSC_CTRL = OSC_CTRL & 0xFE;        // отключение системной синхронизации от внутреннего RC-генератора частотой 2 МГц
	
	// Config Port
	PORTD.DIR = 0x04;
													
	StartUsartD1();
	
	sei();
	PMIC_CTRL = 1;
			
while (1)
      {
	  PORTD.OUTSET =0x04;				// Led
      asm("NOP");
	  if (cnt != 0) {
			if (cnt == 0x55) for (i=0;i<5;i++) sendChar1(buf[i]);
			else for (i=0;i<5;i++) sendChar1(dat[i]); }
			cnt = 0;
			  
      }
}
Изображение

Re: Usart в Xmega

Добавлено: Пн июл 27, 2015 15:28:57
eess9
Сложно сказать. Код выглядит нормально. Уверены, что кварц 12МГц не битый? Конденсаторы на землю есть? Попробуйте заменить кварц.
Первое, что я всегда делаю в проектах с uart это шлю с головы разнообразные данные и отправляю назад в терминал принятый байт. Когда начинает приходить то, что отправляю, со скоростью все норм, можно крутить логику. Попробуйте так.

Re: Usart в Xmega

Добавлено: Пн июл 27, 2015 15:57:52
Nosaer
Кварцы я уже и на 8 ставил и использовал чужой код для его запуска, и на 11,052 ставил. Конденсаторы на 15пф, по документации.
Сейчас попробую реализовать эхо. как вы посоветовали

Re: Usart в Xmega

Добавлено: Пн июл 27, 2015 16:12:16
Nosaer
Организовал эхо, и честно говоря немного в непонятках

При отправке этого гребанного символа U, в ответе получаю 55 FF, при отправке любого другого символа FF нет. Из-за этих FF, я столько вечеров убил на это.

Не стабильность по частоте все еще есть, если эхо(пересылка по одному символу) еще и работает на 9600, то массив нормально приходит только на 9500 примерно. И то иногда все таки проходит ошибка, но уже гораздо реже. Думаю методом подбора получится решить проблему со скоростью

Re: Usart в Xmega

Добавлено: Вт июл 28, 2015 09:22:16
eess9
Тогда я бы сделал так: закомментировал все настройки тактирования. Контроллер останется на внутренних 2МГц железно. Далее рассчитал для 2МГц настройки скорости uart и проверил бы эхо. Если странное поведение останется, виноват UART, можно смело менять контроллер. Если все будет OK, то беда с тактированием. В таком случае, насколько критичен внешний кварц? Используйте внутренний на 32МГц, например. Если, конечно, он будет адекватно работать.

А вообще дебагера у вас нет? Он бы сильно помог найти место где порылась собака.

Re: Usart в Xmega

Добавлено: Ср июл 29, 2015 04:57:15
Nosaer
Дебагера к сожалению нет :(

Пока подобрал методом подгона к 9600. Плюс нашел ошибку в программе из-за которой обрабатывались не все отправленные команды.
Буду надеяться, что когда с макетки перейду на нормальную разведенную плату и поставлю уже другой контроллер проблема исчезнет.
Большое спасибо за помощь=)