Перейти к содержанию
    

Ошибки чтения STM8L

STM8L152C6, работа с LCD. отладка с использованеим stm8l discovery в IAR'e.

Периодически происходят ошибки чтения памяти. Они не всегда появляются при отладке, но всегда при обычной работе контроллера, что вызывает его перезапуск.

текущая версия кода:

#include "iostm8l151c6.h"
#include "LCD.h"


#define RTC_vector 0x06

#define T_CPU 0.0625  // 1/частота ядра в мегагерцах = период такт. сигнала в микросек.

//Глобальные переменные

/* Описание глобальных переменных 
***global_flags_LCD***
биты [0:1] - флаги навигации по меню (кнопка BUT1)
//00 - 1 строка 
01 - 2 строка
10 - 3 строка
биты [2:3] - флаги глубины нахождения в меню
00 - основное меню
01 - подменю 1 порядка
10 - подменю 2 порядка
11 - не в меню, на экране - процесс измерения
***global_flags_ADC**
биты [0:1] - флаги текущего режима работы АЦП 
00 - АЦП выкл
01 - непрерывный режим преобразование  
01 - периодич. N - число преобразований
*/
static unsigned char global_flags_LCD;
//static unsigned char global_flags_ADC;

//Прототипы функций
void delay_mcs(unsigned int); 

void LCD_initialization(void);
void set_main_menu_LCD(void);  
void send_command_to_LCD(unsigned char);
void send_data_to_LCD(unsigned char);
void set_CGRAM_adress(unsigned char);
void set_DDRAM_adress(unsigned char);
void wait_busy_flag(void);

//Обработчики прерываний

#pragma vector=EXTID_vector         
__interrupt void buttons_interrupt(void)
{
 if (PD_IDR_bit.IDR0==0) // прерывание на PD0 - навигация по меню
 {
   if ((global_flags_LCD&0x03)==0x00) 
   {
     global_flags_LCD=(global_flags_LCD&0xFC)|0x01;
     set_DDRAM_adress(0xC0);
     goto exit0;
   }
   if ((global_flags_LCD&0x03)==0x01)
   {
     global_flags_LCD=(global_flags_LCD&0xFC)|0x02;
     set_DDRAM_adress(0x90);
     goto exit0; 
   }
   if ((global_flags_LCD&0x03)==0x02)
   {
     global_flags_LCD=(global_flags_LCD&0xFC)|0x00;
     set_DDRAM_adress(0x80);
     goto exit0;
   }
 }
exit0:
 while (PD_IDR_bit.IDR0==0) {} //ожидание отпускания кнопки

 //прерывание на PD1
 if (PD_IDR_bit.IDR1==0) 
 {
   if ((global_flags_LCD&0x0C)==0x00)
   {
      if ((global_flags_LCD&0x03)==0x00) //если выбран режим непрерывного измерения (1 строка в меню)
      {
        send_command_to_LCD(clear_display);
        send_data_to_LCD(0x21);    //TEST
        //global_flags_ADC=0x01; //запуск непрерывного преобразования с отображением рез-ов на экране
        goto exit1;
      }
      if ((global_flags_LCD&0x03)==0x01) //если выбран режим периодич измерений      
      {
         send_data_to_LCD(0x23);    //TEST
      }
   }  
 }
exit1:
 while (PD_IDR_bit.IDR1==0) {} //ожидание отпускания кнопки
 EXTI_SR2_bit.PDF=1; //сброс флага прерывания
 delay_mcs(200); 
}


int main( void )
{
 //настройка тактирования. 
 //тактирование от 16Мгц внутреннего ист. HSI
 CLK_CKDIVR=0x00;
 //настройка порта для кнопок
 PD_DDR=0xFC;  //порт D[0:1] на вход, D[2:7] - на выход
 PD_CR1=0xFF;  //D[0:1] - с подтяжкой; D[2:7] - push-pull
 PD_CR2=0x03;  //D[0:1] - разр. прерывания; 
 EXTI_CR3=0x00;  //прерывание на PD[0:3] по спаду и низкому уровню //0 и 1 битах портов возникает по спаду 
 EXTI_CONF_bit.PDLIS=1;  //PD[3:0] - исп. для EXTID 
 //настройка неисп. портов
 PA_DDR=0xff;
 PA_CR1=0xff;
 PA_ODR=0xff;
 delay_mcs(800000);
 PA_ODR=0x00;
 PC_DDR=0xff;
 PC_CR1=0xff;
 PF_DDR=0xff;
 PF_CR1=0xff;
 global_flags_LCD=0x00;
 //global_flags_ADC=0x00;
 LCD_initialization(); 
 set_main_menu_LCD();
 asm("RIM");
 while(1) 
 {

 }
}

void delay_mcs(unsigned int mcs)
{
 unsigned long temp=0;
 temp=(mcs*10000)/(T_CPU*10000);
 for (unsigned int i=0;i<temp;i++) {}
}
void LCD_initialization(void)
{
 PE_DDR=0x07;  //PE[0:2] - выход. PE0 - E, PE1 - R/W, PE2 - RS
 PE_CR1=0x07; //PE[0:2] - push-pull
 PE_ODR_bit.ODR1=0; //R/W - запись на LCD
 PE_ODR_bit.ODR2=0; //RS - команда
 PB_DDR=0xff;  //порт B - выход на LCD
 PB_CR1=0xff;  //push-pull
 delay_mcs(50000);
 PE_ODR_bit.ODR0=1; // E - 1
 PB_ODR=bus_8__st_2__sym_l;
 delay_mcs(400);
 PE_ODR_bit.ODR0=0; // E - 0
 delay_mcs(800);
 PE_ODR_bit.ODR0=1; // E - 1
 PB_ODR=bus_8__st_2__sym_l;
 delay_mcs(400);
 PE_ODR_bit.ODR0=0; // E - 0
 delay_mcs(1000);
 PE_ODR_bit.ODR0=1; // E - 1
 PB_ODR=bus_8__st_2__sym_l;
 delay_mcs(400);
 PE_ODR_bit.ODR0=0; // E - 0
 wait_busy_flag();  //если busy flag=0, продолжить инициализацию
 send_command_to_LCD(clear_display);
 wait_busy_flag();  //если busy flag=0, продолжить инициализацию
 send_command_to_LCD(disp_on__s_cursor);
 wait_busy_flag();  //если busy flag=0, продолжить инициализацию
 send_command_to_LCD(inc_adr__no_shift);
}
void set_main_menu_LCD(void)
{
 set_DDRAM_adress(0x80);  //1 строка
 send_data_to_LCD(0x20); //_
 send_data_to_LCD(0x48);
 send_data_to_LCD(0x45);
 send_data_to_LCD(0xA8);
 send_data_to_LCD(0x50);
 send_data_to_LCD(0x45);
 send_data_to_LCD(0x50);
 send_data_to_LCD(0xAE);
 send_data_to_LCD(0x42); 
 send_data_to_LCD(0x20); //_
 send_data_to_LCD(0xA5);
 send_data_to_LCD(0xA4);
 send_data_to_LCD(0x4D);


 set_DDRAM_adress(0xC0);  //2 строка
 send_data_to_LCD(0x20);  //_
 send_data_to_LCD(0xA8);
 send_data_to_LCD(0x45);
 send_data_to_LCD(0x50);
 send_data_to_LCD(0xA5);
 send_data_to_LCD(0x4F);
 send_data_to_LCD(0xE0);
 send_data_to_LCD(0x20);  //_
 send_data_to_LCD(0xA5);
 send_data_to_LCD(0xA4);
 send_data_to_LCD(0x4D);

 set_DDRAM_adress(0x90);  //3 строка
 send_data_to_LCD(0x20);  //_
 send_data_to_LCD(0x42);
 send_data_to_LCD(0xAE);
 send_data_to_LCD(0x42);
 send_data_to_LCD(0x4F);
 send_data_to_LCD(0xE0);
 send_data_to_LCD(0x20); //_
 send_data_to_LCD(0xA8);  
 send_data_to_LCD(0x4F);
 send_data_to_LCD(0x20); //_
 send_data_to_LCD(0x55);
 send_data_to_LCD(0x41);
 send_data_to_LCD(0x52);  
 send_data_to_LCD(0x54);  
 set_DDRAM_adress(0x80);  //1 строка 

}

void send_command_to_LCD(unsigned char command)
{
 wait_busy_flag();  //если busy flag=0, продолжить 
 PE_ODR_bit.ODR1=0; //R/W - запись на LCD
 PE_ODR_bit.ODR2=0; //RS - команда
 PE_ODR_bit.ODR0=1; // E - 1
 PB_DDR=0xff;  //порт B - выход на LCD
 PB_CR1=0xff;  //push-pull
 PB_ODR=command;
 delay_mcs(40);
 PE_ODR_bit.ODR0=0; // E - 0
 PB_DDR=0x00; //порт B - вход от LCD
}
void send_data_to_LCD(unsigned char data)
{
 wait_busy_flag();  //если busy flag=0, продолжить 
 PE_ODR_bit.ODR1=0; //R/W - запись на LCD
 PE_ODR_bit.ODR2=1; //RS - данные
 PE_ODR_bit.ODR0=1; // E - 1
 PB_DDR=0xff;  //порт B - выход на LCD
 PB_CR1=0xff;  //push-pull
 PB_ODR=data;
 delay_mcs(40);
 PE_ODR_bit.ODR0=0; // E - 0
 PB_DDR=0x00; //порт B - вход от LCD
}
/*переключает адресацию на CGRAM, входной параметр adress - задает адрес */
void set_CGRAM_adress(unsigned char adress)
{
 wait_busy_flag();  //если busy flag=0, продолжить 
 PE_ODR_bit.ODR1=0; //R/W - запись на LCD
 PE_ODR_bit.ODR2=0; //RS - команда
 PE_ODR_bit.ODR0=1; // E - 1
 PB_DDR=0xff;  //порт B - выход на LCD
 PB_CR1=0xff;  //push-pull 
 PB_ODR=adress;
 delay_mcs(40);
 PE_ODR_bit.ODR0=0; // E - 0
 PB_DDR=0x00; //порт B - вход от LCD
}
/*переключает адресацию на DDRAM, входной параметр adress - задает адрес */
void set_DDRAM_adress(unsigned char adress)
{
 wait_busy_flag();  //если busy flag=0, продолжить
 PE_ODR_bit.ODR1=0; //R/W - запись на LCD
 PE_ODR_bit.ODR2=0; //RS - команда
 PE_ODR_bit.ODR0=1; // E - 1
 PB_DDR=0xff;  //порт B - выход на LCD
 PB_CR1=0xff;  //push-pull
 PB_ODR=adress;
 delay_mcs(40);
 PE_ODR_bit.ODR0=0; // E - 0 
 PB_DDR=0x00; //порт B - вход от LCD
} 
void wait_busy_flag(void)
{
 unsigned char busy_flag;
 PE_ODR_bit.ODR1=1; //R/W - чтение с LCD
 PE_ODR_bit.ODR2=0; //RS - команда 
 PB_DDR=0x00;  //порт B - вход с LCD
 PB_CR1=0xff;  //с подтяжкой
 PB_CR2=0x00;  //без прерывания 
cycle:
 PE_ODR_bit.ODR0=1; // E - 1
 delay_mcs(10);
 PE_ODR_bit.ODR0=0; // E - 0
 busy_flag=PB_IDR&0x80;
 busy_flag=busy_flag>>7;
 if (busy_flag!=0x00) goto cycle;
} 
/*
void delay_mcs(unsigned int mcs)
{



}
*/

Из-за чего могут быть ошибки чтения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

проблему решил!

перезагрузка была из-за настройки этих портов:

PC_DDR=0xff;
  PC_CR1=0xff;
  PF_DDR=0xff;
  PF_CR1=0xff;

во время борьбы с лишними прерываниями я все порты неиспользуемые бездумно поставил на вход и подтянул вверх.

перезагрузка была, вероятно из-за того, что С0 и С1 (вроде бы) используются для подключения внешнего кварца и работают в режиме открытого стока (что то такое читал я в даташите).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...