Lyt 0 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба 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) { } */ Из-за чего могут быть ошибки чтения? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lyt 0 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба проблему решил! перезагрузка была из-за настройки этих портов: PC_DDR=0xff; PC_CR1=0xff; PF_DDR=0xff; PF_CR1=0xff; во время борьбы с лишними прерываниями я все порты неиспользуемые бездумно поставил на вход и подтянул вверх. перезагрузка была, вероятно из-за того, что С0 и С1 (вроде бы) используются для подключения внешнего кварца и работают в режиме открытого стока (что то такое читал я в даташите). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться