Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ошибки чтения STM8L
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Lyt
STM8L152C6, работа с LCD. отладка с использованеим stm8l discovery в IAR'e.
Периодически происходят ошибки чтения памяти. Они не всегда появляются при отладке, но всегда при обычной работе контроллера, что вызывает его перезапуск.
текущая версия кода:
CODE
#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)
{



}
*/

Из-за чего могут быть ошибки чтения?
Lyt
проблему решил!
перезагрузка была из-за настройки этих портов:
Код
PC_DDR=0xff;
  PC_CR1=0xff;
  PF_DDR=0xff;
  PF_CR1=0xff;

во время борьбы с лишними прерываниями я все порты неиспользуемые бездумно поставил на вход и подтянул вверх.
перезагрузка была, вероятно из-за того, что С0 и С1 (вроде бы) используются для подключения внешнего кварца и работают в режиме открытого стока (что то такое читал я в даташите).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.