ATmega48, внутренний RC генератор и SPI

Обсуждаем контроллеры компании Atmel.
Ответить
Мудрый кот
Аватара пользователя
Сообщения: 1867
Зарегистрирован: Ср янв 23, 2008 22:11:54
Откуда: Калининград

Сообщение GRAF »

Решил применить внутренний тактовый RC генератор на 8 МГц. Проблема в том, что программа виснет на этапе настройки SPI - на записи в регистр SPCR. От внешнего кварца все работает. В протеусе работает как с внешним, так и с внутренним. Код в CVAVR.
Спойлер

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

#include "c55_lcd.h"
#include "mega48.h"



//Определения функций--------------------------------------- 
void lcd_GoToXY(char x, char y);
void lcd_Init(void);
void lcd_Clear(void);
void lcd_Contrast(char contrast);
void lcd_PutChar(char c);
void lcd_PutStr(char *s);

void SPI_Init(void);
void SPI_Transmit(char cData, LcdCmdData cd);

bit rad=0;




//SPI------------------------------------------------------
void SPI_Init(void)
{
    /* Set MOSI and SCK output */
    DDRB|= LCD_MOSI_PIN | LCD_CLK_PIN;
    /* Enable SPI, Master, set clock rate fck/16 */
    //SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
    SPCR=0x51;
}

void SPI_Transmit(char cData, LcdCmdData cd)
{
    PORTD &= ~LCD_CE_PIN;
    if ( cd == LCD_DATA )
    PORTB |= LCD_DC_PIN;
    else PORTB &= ~LCD_DC_PIN;
    /* Start transmission */
    SPDR = cData;
    /* Wait for transmission complete */
    while(!(SPSR & (1<<SPIF)));
    PORTD |= LCD_CE_PIN;
}
//----------------------------------------------------------

//Переход по координатам------------------------------------
void lcd_GoToXY(char x, char y)
{
    SPI_Transmit( 0x80 | x, LCD_CMD );
    SPI_Transmit( 0x41 + y, LCD_CMD );
}
//----------------------------------------------------------




//Инициализации дисплея------------------------------------
void lcd_Init(void)
{
    int i=0; 
    //настройка порта B на вывод, лог. "0" по умолчанию-----------------------------------------
    DDRD |= LCD_RST_PIN | LCD_CE_PIN;
    DDRB |= LCD_DC_PIN;
    DDRC |= LCD_PWR_PIN;

    PORTC.2=0;
    PORTD |= LCD_RST_PIN | LCD_CE_PIN;
    PORTB |= LCD_DC_PIN;
    //LCD_PORT1|= LCD_PWR_PIN;
    
    //------------------------------------------------------------------------------------------
    
    //LCD_PORT1|= LCD_PWR_PIN;
    
    PORTD&=~LCD_RST_PIN; //подача сброса на дисплей 
   
    for (i = 0; i < 3000; i++);
    
    
    PORTC|= LCD_PWR_PIN;
    
    for (i = 0; i < 3000; i++);
    
    PORTD&=~LCD_CE_PIN;  
    
    for (i = 0; i < 3000; i++);
      
    PORTD|=LCD_RST_PIN;
    
    for (i = 0; i <3000; i++);
    
    PORTD |= LCD_CE_PIN;   

    SPI_Transmit(0x21,LCD_CMD);        //extended commands
   
    SPI_Transmit(0xC8,LCD_CMD);        //Vop (contrast) 
    
    SPI_Transmit(0x06,LCD_CMD);        //Temp coefficient
    
    SPI_Transmit((0x10)|0x02,LCD_CMD);        //LCD bias mode 1:48
    
    SPI_Transmit(0x45,LCD_CMD);        //Korrection : s 1 stroki
    
    SPI_Transmit(0x20,LCD_CMD);        //LCD standard, Horiz addressing
    
    SPI_Transmit(0x0C,LCD_CMD);        //display control LCD normal mode
    
    /*
    SPI_Transmit( 0x21, LCD_CMD ); // Включаем расширенный набор команд (LCD Extended Commands)
    SPI_Transmit( 0xC8, LCD_CMD ); // Установка контрастности (LCD Vop)
    SPI_Transmit( 0x06, LCD_CMD ); // Установка температурного коэффициента (Temp coefficent)
    SPI_Transmit( 0x13, LCD_CMD ); // Настройка питания (LCD bias mode 1:48)
    SPI_Transmit( 0x20, LCD_CMD ); // Включаем стандартный набор команд и горизонтальную адресацию (LCD Standard Commands,Horizontal addressing mode)
    SPI_Transmit( 0x0C, LCD_CMD ); // Нормальный режим (LCD in normal mode)
    */
    
    for (i = 0; i < 1000; i++);
    lcd_Clear();
    for (i = 0; i < 1000; i++);
}
//-----------------------------------------------------------



//Очистка экрана---------------------------------------------
void lcd_Clear(void)
{
    int i=0;
    lcd_GoToXY(0,0);
    for (i = 0; i < 102*8; i++) SPI_Transmit(0, LCD_DATA);
}
//-----------------------------------------------------------



//Контрастность изображения----------------------------------
void lcd_Contrast (char contrast)
{
    SPI_Transmit(0x21, LCD_CMD);
    SPI_Transmit(0x80 | contrast, LCD_CMD);
    SPI_Transmit(0x20, LCD_CMD);
}
//-----------------------------------------------------------




//Посылка символа--------------------------------------------
void lcd_PutChar(char c)
{
    char i=0;
    for (i=0;i<5;i++)
    {
        
        if(c==0xA8)
        {
            SPI_Transmit(LCD_FONT[96][i], LCD_DATA);
        }
        else if(c==0xB8)
        {
            SPI_Transmit(LCD_FONT[97][i], LCD_DATA);
        }
        else if(c>=0xC0)
        {
            SPI_Transmit(LCD_FONT[c-94][i], LCD_DATA);
        }
        else
        {   
         
            SPI_Transmit(LCD_FONT[c-32][i], LCD_DATA);
        }
    }
}  
    

//Посылка строки---------------------------------------------
void lcd_PutStr(char *s)
{
    while (*s != '\0')
    lcd_PutChar(*s++);
}
//-----------------------------------------------------------

void main()
{
#pragma optsize-
CLKPR=(1<<CLKPCE);//предделитель тактовой частоты 1
CLKPR=0x00;
#pragma optsize+ 
    
    
    SPI_Init(); 
    lcd_Init();
    lcd_Contrast(0x64);//0x64

    

    
    TCCR0B|=(1<<CS00)|(1<<CS01)|(1<<CS02);//ext. clock on T0 pin. Rising edge.
    OCR0A=20;
    TIMSK0|=(1<<OCIE0A)|(1<<TOIE0);
    
    
    
    DDRB.2=1;
    PORTB.2=1;//LED
    
   
    
    SREG|=(1<<SREG_I);
    
     lcd_GoToXY(0,0); 
    
    lcd_PutStr("!!");
    
   
    while(1);


}

interrupt [TIM0_OVF] void tim0_ovf_isr(void)
{

    PORTB.2=0;
} 

interrupt [TIM0_COMPA] void tim0_cmpa_isr(void)
{

    PORTB.2=1;

} 
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1867
Зарегистрирован: Ср янв 23, 2008 22:11:54
Откуда: Калининград

Сообщение GRAF »

Почему проблема проявляется только при использовании внутреннего генератора, не знаю. Решается подтяжкой SS к Vcc в самом начале программы, либо при отключенной оптимизации.

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

#pragma optsize-
PORTB.2=1;  
#pragma optsize+ 
Реклама
Ответить

Вернуться в «AVR»