у меня используется в функциях и прерываниях без volatile и прекрасно работает. Но я не использую оптимизатор, или, если использую, смотрю, что он там наоптимизировал.
ну, не совсем в них Вам просто надо изучить тонкости оптимизатора, методы отладки и всё будет норм. Потом станет привычным. Если бы VladislavS не сказал, я бы и не вспомнил про оптимизатор.
Правильно ли я понял, что его обязательно нужно применять при программировании любых МК, если переменная используется(читай меняет свое значение) в функциях и прерываниях?
Проблемы в этих настройках, конечно же, нет. Оптимизация должна быть включена, чтобы код был быстрым или компактным. Проблема в том, что нужно представлять что делает оптимизатор и выполнять минимальные требования при написании кода. Их не очень много, но на одно из них вы наступили. В следующий раз учтёте уже.
Перешел к изучению АЦП в STM8S. Подскажите, пожалуйста, правильно ли я понимаю, что результат преобразования АЦП будет записан в регистры ADC_DRL и ADC_DRH в двоичной системе исчисления? Если это так, то как перевести результат преобразования в десятичную систему исчисления и присвоить его переменной?
Это условности, всё в этом электронном мире в двоичной системе. Но вообще, системы счисления изучают до программирования, Вы обязаны знать как минимум ещё две: двоичную и шестнадцатеричную. И будет лучше, если прочитаете про них в книжке. Но в кратце: указанные Вами регистры состоят из битов, ADC_DRL из восьми, а ADC_DRH из двух или четырёх (я не помню, да и возможно там есть выравнивание и тогда всё наоборот). И есть у нас некая переменная ADC_Result, размер которой 16 бит. Если нам надо в неё поместить содержимое двух регистров, то мы можем представить всё это как длинный горизонтальный ряд ящиков. Ящик = бит. Ящики справа - младшие. Ящики слева -старшие. Младшие всегда заполняются первыми. Помещаем младшие ящики: ADC_Result = ADC_DRL; Теперь надо добавить старшие. Если так же присвоим - они просто заполнят опять первые младшие, то есть, нам надо принудительно их сдвинуть в старшие: ADC_DRH << 8 и вся запись будет ADC_Result = ((unsigned short)(ADC_DRH << 8 )) | ADC_DRL;
и совершенно неважно, какая там система. Если напишите ADC_Result > 4096 ? будет сравнение с десятичной, если ADC_Result + 0xDF - сложение с шестнадцатеричной и т.д. Но программировать без знания двоичной и особенно шестнадцатеричной систем невозможно. Книжка приложена, осталось лишь прочитать.
Большое спасибо за ответ. А за книжечку отдельная благодарность. Обобщенно системы исчисления я знаю( я думаю, что знаю ). С книжкой обязательно ознакомлюсь. Если ничего нового не узнаю, то как минимум освежу знания. В принципе, так как вы сказали, так я все это и понимал. Единственное, думал, раз число записано в двоичном виде, то нужно его переводить в десятичную систему(мне нужно число именно в десятичной системе). И даже уже начал писать код для перевода чисел, но потом остановился. Мне пришла мысль, что я изобретаю велосипед. До меня все уже придумано. Либо есть есть стандартная функция, либо компилятор сам это сделает. Собственно поэтому и решил уточнить. Как оказалось, это было не зря!
и вся запись будет ADC_Result = ((unsigned short)(ADC_DRL << 8 )) | ADC_DRL;
Еще хотел уточнить. Вы случайно не допустили опечатку? Не вот так ли должна выглядеть конечная запись: ADC_Result = ((unsigned short)(ADC_DRH << 8 )) | ADC_DRL; Это если выравнивание по правому краю А если по левому то вот так: ADC_Result = ((unsigned short)(ADC_DRL >> 8 )) | ADC_DRH; ?
Спасибо за ссылку. Попробую разобраться. Но признаться честно, мне пока тяжело читать чужой код в силу нехватки знаний. Со словарем-то(с интернетом) я читаю, но очень долго
Перешел к изучению АЦП. Решил переписать представленную выше программу. На ЖКИ должно отображаться 3 старших знака максимального измеренного значения в милливольтах(например, 330, если значение равно 3300). Но по факту у меня какой-то мусор на ЖКИ. Спойлер
Код:
#include "IOSTM8S103F3.h" volatile unsigned short z=0, x=0, y=111,L_1,L_2,L_3; volatile int m=0, t; volatile char i=1,j=0,n=0,k=1;
PC_ODR_bit.ODR3 = 1; // Высокий уровень на выходе PC_CR1_bit.C13 = 1; // push-pull PC_DDR_bit.DDR3 = 1; // Выход com D9 }
void com_D9_() { PC_ODR_bit.ODR3 = 0; // Низкий уровень на выходе com D9 }
void COM() { switch(k) { case 1: com_D12(); break; case 2: com_D12_(); break;
case 3: com_D11(); break; case 4: com_D11_(); break;
case 5: com_D10(); break; case 6: com_D10_(); break;
case 7: com_D9(); break; case 8: com_D9_(); break; } }
void SEG() {
// DIGIT_1 i=!i; if (n == 1) { if ((j == 7) ^ (j == 6)) { PD_ODR_bit.ODR2 = ZNAK[j]; // Фаренгейт } } else { PD_ODR_bit.ODR2 = DIGIT[L_1][i][j]; // seg D14 } i=!i; PC_ODR_bit.ODR7 = DIGIT[L_1][i][j]; // seg D13
// DIGIT_2 i=!i; if (n ==2) { if ((j == 7) ^ (j == 6)) { PD_ODR_bit.ODR6 = ZNAK[j]; // Вилка } } else { PD_ODR_bit.ODR6 = DIGIT[L_2][i][j]; // seg D5 } i=!i; PA_ODR_bit.ODR1 = DIGIT[L_2][i][j]; // seg D6
// DIGIT_3 i=!i; if (n == 3) { if ((j == 7) ^ (j == 6)) { PA_ODR_bit.ODR3 = ZNAK[j]; // Цельсий } } else { PA_ODR_bit.ODR3 = DIGIT[L_3][i][j]; // seg D8 } i=!i; PA_ODR_bit.ODR2 = DIGIT[L_3][i][j]; // seg D7 } int main (void) { CLK_CKDIVR=0; // установка делителя частоты процессора равного 1
ADC_CSR_bit.AWD=0; //запрет ожидания сигнала от аналогового сторожевого таймера ADC_CSR_bit.EOCIE=0; //прерывание по окончанию преобразования запрещено ADC_CSR_bit.AWDIE=0; //прерывание от сторожевого таймера запрещено ADC_CSR_bit.CH=0x04; //канал AIN4 ADC_CR1_bit.SPSEL=0x04; //выбор делителя частоты. Макс. АЦП F=4МГц при VDD=3.3, при VDD=4В F=6МГц ADC_CR1_bit.CONT=0; //одиночное преобразование ADC_CR2_bit.EXTTRIG=0; //преобразование по внешнему событию запрещено ADC_CR2_bit.ALIGN=0; // выравнивание результата преобразования "по правому краю" ADC_CR3_bit.DBUF=0; //Буфер данных отключен. Результат преобразования в ADC_DRH и ADC_DRL ADC_CR3_bit.OVR=0; //очистка флага перед запуском АЦП ADC_CR1_bit.ADON=1; //подключение АЦП к источнику питания
PD_DDR_bit.DDR3 = 0; // Вход.Детектор напряжения. Скорей всего инициализировать PD3 не нужно PD_CR1_bit.C13 = 1; // Подтягивающий резистор отключен PD_CR2_bit.C23 = 0; // Прерывая запрещены
Логику кода не рассматривал, но на "первый взгляд::
Код:
y=x*3300000/1023;
Нужен результат в микровольтах?? Переведите формулу в милливольт. Даже в милливольт, y в умножении далеко из граници unsigned short. (Eсли компилятор не делает) может использовать temp переменную более высокой разрядности и последующее casting после деления для y.
Код:
unsigned long tmp = x * 3300; tmp /= 1023; y = (unsigned short)tmp;
Да, ошибся нулями. Точнее сказать, забыл стереть после экспериментов. Но проблема не в этом. Даже если я явно присвою y определенное значение, на индикаторе мусор Спойлер
Код:
while(1) { SEG(); COM(); if ((ADC_CSR_bit.EOC==1)&(t==1000)) { t=0; x = ((unsigned short)(ADC_DRH << 8 )) | ADC_DRL; //записывае данные из регистров ADC_DRL и ADC_DRH в переменную PB_ODR_bit.ODR5 = !PB_ODR_bit.ODR5; // Индикатор входа в тело оператора if (x>y) { y=111; DELENIE(); } ADC_CR1_bit.ADON=1; // запускаем преобразование } }
Сейчас этот форум просматривают: Majestic-12 [Bot] и гости: 39
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения