ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
19 апреля
795691 Топик полностью
Гyдвин, волшебник (20.11.2017 15:23, просмотров: 825) ответил Гyдвин на Вступил, йопть, в STM8. Сразу такая граблЯ - пин PD1 порта D после сброса используется для SWIM. Любая запись в регистр DDR порта, вырубает отладку. Бит 1, естественно,=0. Извечный русский вопрос к уже вступившим: Кто виноват и что делать? Отладка
Вступил. Вполне даже неплох этот STM8, если прикрыть глаза на французские шалости. Понравилась отладка. Шустрая, много точек останова. Даже в таком мелком чипе. Отладчики MSP, AVR и PIC отдыхают. Внутри история болезни и стационарного лечения ;) Может кому пригодится: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Пациент - китайский идикатор напряжения и тока на STM8 в ssop20 // Место жительства: https://ru.aliexpr …r-online-shopping.html // // Анамнез: бред, навязчибые попытки показывать "направление на Пентагон","погоду за бортом" вместо исполнения штатных обязанностей. // // Дагноз: идиотские делители в каналах измерения, использование малого участка диапазона встроенного АЦП. // Положительные моменты - пациет немного кушает при достаточно ярком индикаторе, имеет стабилизатор/опору с неплохими характеристиками. // // Операционное вмешательство: // Пересадка LM358 на r2r output MCP602 для увеличения диапазона выходного сигнала // Замена/подгонка резисторов в делителе напряжения и обратной связи ОУ токового канала // с целью нормировать входные сигналы к полному диапазону АЦП. // // Консервативное реанимационное лечение: // Не пинать! Интерн провел первую операцию на STM8. // Говнокодие, ибо "шармоватое" распределение аж 4 портов в 16 пин в STM8S003F3 не позволяет "изобразить красиво" // А может просто интерн не умеет их готовить - STM еще те затейники :) // Ну и что китайцы выродили/развели, то и приходится лечить... // Не пользовал прерывания. Ини пациету они в этом случае нафиг не нужны. // Так проще выровнять яркость свечения знакомест индикаторов (красные/синие, нагрузочные способности портов). // Инструменты: // IAR v 1.4. Более старшие не ставятся на XP :( // Оптимизация LOW или Medium. // При оптимизации "High" IAR v1.4 делает даже этот простенький линейный код неработоспособным. Пациент дохнет :) // // Эпикриз: пациенту стало значительно лучше. // // Амбулаторное лечение: // Обратиться с светилам медицины ST для дальнейших консультаций и назначений. // Есть возможность переучить для другого рода деятельности. // Например, после несложной хирургии и лечения использовать как дешевый законченный встраиваемый индикатор // c последовательным интерфейсом. Ибо RX,TX uart разведены на разъем. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "stm8s.h" #include <stdio.h> //для выравнивания яркости знакомест #define DELAY 600 // время индикации символа разрядов 1..3 #define DELAY1 500 // время индикации символа разрядов 4..5 #define DELAY2 800 // время индикации символа разряда 6 #define N_AVERAGE 256 // количество замеров ADC для усреднения (д.б. кратно 2 и желательно степень 2) unsigned int cnt_adc; // char disp[8]=" 00000"; unsigned long adc_U;// сумма adc U для усреднения unsigned long adc_I;// сумма adc I для усреднения unsigned int tmp_i;// для процедуры калибровки смещения ОУ в канале измерения тока unsigned int sav_i;// для установки позиции точки индикатора тока uint16_t *zero_I = (uint16_t *)0x4000; // калибровка начального смещения ОУ тока в EEPROM void delay(long t) { long i; for (i = 0;i < t;i++); } void work_adc(void) { unsigned int tmp; ADC1->CSR = 0x04; // AIN4 (PD3) Канал напряжения ADC1->CR1 |= 0x01; // start conversion while (!(ADC1->CSR & 0x80)); // wait for end of conversion tmp= ADC1->DRL; tmp |= (ADC1->DRH << 8); adc_U+=tmp; ADC1->CSR = 0x03; // AIN3 (PD2) Канал тока ADC1->CR1 |= 0x01;// start conversion while (!(ADC1->CSR & 0x80)); // wait for end of conversion tmp= ADC1->DRL; tmp |= (ADC1->DRH << 8); tmp_i=tmp;// в tmp_i останется "сырое" значение тока после выполнения функции // компенсация смещения ОУ канала измерения тока if (tmp < *zero_I) tmp=0; else tmp= tmp - *zero_I; adc_I+=tmp; cnt_adc++; if (cnt_adc==N_AVERAGE) { cnt_adc=0; adc_U= adc_U/N_AVERAGE; // вычисляем среднее напряжения adc_U/=4; //масштабируем значение напряжения для вывода на индикатор // 12V = 480adc, max 25.575V = 1023adc adc_I= adc_I/(N_AVERAGE/2); // вычисляем среднее тока + масштабируем + некое повышение разрядности для вывода на индикатор. 10A = 500adc*2 sav_i=adc_I; // запомним тасштабированное значение тока sprintf(disp,"%03lu%03lu", adc_U,adc_I); if (disp[0]=='0') disp[0]=' '; //удалим незначащий нуль adc_I=0; // обнулим для следуюшего цикла adc_U=0; } } void out_7led_dig(char numb_dig) // вывод очередного символа в 7LED из строки disp { GPIOC->ODR&= ~(1<<5); //PC5 (DP) // сотрем точку if (numb_dig == 1) GPIOC->ODR|= (1<<5); //PC5 (DP) // выведем точку (напряжение) if ((sav_i < 1000)&&(numb_dig == 3)) GPIOC->ODR|= (1<<5); //PC5 (DP) // выведем точку (ток < 10А) if ((sav_i > 999)&&(numb_dig == 4)) GPIOC->ODR|= (1<<5); //PC5 (DP) // выведем точку (ток >= 10А) switch (disp[numb_dig]) { case '0': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR|= (1<<7); // PC7 (E) GPIOC->ODR|= (1<<4); // PC4 (F) GPIOA->ODR&= ~(1<<2); // PA2 (G) break; case '1': GPIOD->ODR&= ~(1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR&= ~(1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR&= ~(1<<4); // PC4 (F) GPIOA->ODR&= ~(1<<2); // PA2 (G) break; case '2': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR&= ~(1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR|= (1<<7); // PC7 (E) GPIOC->ODR&= ~(1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; case '3': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR&= ~(1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; case '4': GPIOD->ODR&= ~(1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR&= ~(1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR|= (1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; case '5': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR&= ~(1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR|= (1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; case '6': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR&= ~(1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR|= (1<<7); // PC7 (E) GPIOC->ODR|= (1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; case '7': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR&= ~(1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR&= ~(1<<4); // PC4 (F) GPIOA->ODR&= ~(1<<2); // PA2 (G) break; case '8': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR|= (1<<7); // PC7 (E) GPIOC->ODR|= (1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; case '9': GPIOD->ODR|= (1<<1); // PD1 (A) GPIOA->ODR|= (1<<3); // PA3 (B) GPIOC->ODR|= (1<<3); // PC3 (C) GPIOC->ODR|= (1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR|= (1<<4); // PC4 (F) GPIOA->ODR|= (1<<2); // PA2 (G) break; default: GPIOD->ODR&= ~(1<<1); // PD1 (A) GPIOA->ODR&= ~(1<<3); // PA3 (B) GPIOC->ODR&= ~(1<<3); // PC3 (C) GPIOC->ODR&= ~(1<<6); // PC6 (D) GPIOC->ODR&= ~(1<<7); // PC7 (E) GPIOC->ODR&= ~(1<<4); // PC4 (F) GPIOA->ODR&= ~(1<<2); // PA2 (G) break; } } void main(void) { CLK->CKDIVR = 0x00; // 16MHz CFG->GCR |= CFG_GCR_SWD; // отключим SWIM // Set ADC ADC1->CR1 = 0x40; //Fadc = Fmaster/8 = 2MHz ADC1->CR2 = 0x08; //Right alignement ADC1->CR1 |= 0x01; // ADC on GPIOD->CR1|= (1<<6); // подтянем PD6 к VDD (это контакт перемычки) delay(100); // задержка стабилизации ADC // процедура калибровки смещения ОУ канала измерения тока при включении if (!(GPIOD->IDR & (1<<6))) // если установлена перемычка (как в китайском оригинале) при включении, запоминаем в EEPROM смещение ОУ "zero_I". При отсутствии тока! { work_adc(); work_adc(); FLASH->DUKR = 0xAE; FLASH->DUKR = 0x56; *zero_I=tmp_i; delay(90000); while (!(GPIOD->IDR & (1<<6))) delay(10000); IWDG->KR = IWDG_KEY_ENABLE; // Пересброс по WDT while ( 1 ); } // Set GPIO GPIOB->DDR = 0xFF; GPIOB->CR1 = 0xFF; GPIOA->DDR = 0xFF; GPIOA->CR1 = 0xFF; GPIOC->DDR = 0xFF; GPIOC->CR1 = 0xFF; GPIOD->DDR = 0x72; // 0111 0010 // PD3,PD2 - вxоды ADC GPIOD->CR1 = 0x72; // 0111 0010 // PD3,PD2 - вxоды ADC GPIOD->ODR|= (1<<4); // PD4 = 1 (0) // общие катоды всех знакомест 7LED (столбцы) GPIOD->ODR|= (1<<6); // PD6 = 1 (1) GPIOD->ODR|= (1<<5); // PD5 = 1 (2) GPIOB->ODR|= (1<<5); // PB5 = 1 (3) GPIOB->ODR|= (1<<4); // PB4 = 1 (4) GPIOA->ODR|= (1<<1); // PA1 = 1 (5) while (1) // цикл по знакоместам { //disp[0] work_adc(); GPIOD->ODR&= ~(1<<4); // PD4 = 0 out_7led_dig(0); delay(DELAY); GPIOD->ODR|= (1<<4); // PD4 = 1 //disp[1] work_adc(); GPIOD->ODR&= ~(1<<6); // PD6 = 0 out_7led_dig(1); delay(DELAY); GPIOD->ODR|= (1<<6); // PD6 = 1 //disp[2] work_adc(); GPIOD->ODR&= ~(1<<5); // PD5 = 0 out_7led_dig(2); delay(DELAY); GPIOD->ODR|= (1<<5); // PD5 = 1 //disp[3] work_adc(); GPIOB->ODR&= ~(1<<5); // PB5 = 0 out_7led_dig(3); delay(DELAY1); GPIOB->ODR|= (1<<5); // PB5 = 1 //disp[4] work_adc(); GPIOB->ODR&= ~(1<<4); // PB4 = 0 out_7led_dig(4); delay(DELAY1); GPIOB->ODR|= (1<<4); // PB4 = 1 //disp[5] work_adc(); GPIOA->ODR&= ~(1<<1); // PA1 = 0 out_7led_dig(5); delay(DELAY2); GPIOA->ODR|= (1<<1); // PA1 = 1 } }