Программирование STM8
Re: Программирование STM8
у меня используется в функциях и прерываниях без volatile и прекрасно работает. Но я не использую оптимизатор, или, если использую, смотрю, что он там наоптимизировал.
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
ну, не совсем в них
Вам просто надо изучить тонкости оптимизатора, методы отладки и всё будет норм.
Потом станет привычным. Если бы VladislavS не сказал, я бы и не вспомнил про оптимизатор.
Потом станет привычным. Если бы VladislavS не сказал, я бы и не вспомнил про оптимизатор.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Программирование STM8
[uquote="Pjatruha@mail.ru",url="/forum/viewtopic.php?p=4484916#p4484916"]Правильно ли я понял, что его обязательно нужно применять при программировании любых МК, если переменная используется(читай меняет свое значение) в функциях и прерываниях?[/uquote]Для простоты считайте, что это так.
Добавлено after 7 minutes 46 seconds:
[uquote="Pjatruha@mail.ru",url="/forum/viewtopic.php?p=4484940#p4484940"]Мне тоже кажется, что проблема в этих настройках:[/uquote]Проблемы в этих настройках, конечно же, нет. Оптимизация должна быть включена, чтобы код был быстрым или компактным. Проблема в том, что нужно представлять что делает оптимизатор и выполнять минимальные требования при написании кода. Их не очень много, но на одно из них вы наступили. В следующий раз учтёте уже.
Добавлено after 7 minutes 46 seconds:
[uquote="Pjatruha@mail.ru",url="/forum/viewtopic.php?p=4484940#p4484940"]Мне тоже кажется, что проблема в этих настройках:[/uquote]Проблемы в этих настройках, конечно же, нет. Оптимизация должна быть включена, чтобы код был быстрым или компактным. Проблема в том, что нужно представлять что делает оптимизатор и выполнять минимальные требования при написании кода. Их не очень много, но на одно из них вы наступили. В следующий раз учтёте уже.
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
VladislavS
Такое я точно не забуду.
Компилятор из переменной делает константу...
Скажи мне кто раньше об этом - ни за что не поверил бы.
Такое я точно не забуду.
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Перешел к изучению АЦП в STM8S. Подскажите, пожалуйста, правильно ли я понимаю, что результат преобразования АЦП будет записан в регистры ADC_DRL и ADC_DRH в двоичной системе исчисления? Если это так, то как перевести результат преобразования в десятичную систему исчисления и присвоить его переменной?
Re: Программирование STM8
Это условности, всё в этом электронном мире в двоичной системе.
Но вообще, системы счисления изучают до программирования, Вы обязаны знать как минимум ещё две: двоичную и шестнадцатеричную. И будет лучше, если прочитаете про них в книжке.
Но в кратце: указанные Вами регистры состоят из битов, 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_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 - сложение с шестнадцатеричной и т.д.
Но программировать без знания двоичной и особенно шестнадцатеричной систем невозможно. Книжка приложена, осталось лишь прочитать.
- Вложения
-
- В помощь изучающим системы счисления.pdf
- (1.38 МБ) 110 скачиваний
Последний раз редактировалось Martian Вт окт 17, 2023 13:29:48, всего редактировалось 1 раз.
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Большое спасибо за ответ. А за книжечку отдельная благодарность.
Обобщенно системы исчисления я знаю( я думаю, что знаю
). С книжкой обязательно ознакомлюсь. Если ничего нового не узнаю, то как минимум освежу знания. В принципе, так как вы сказали, так я все это и понимал. Единственное, думал, раз число записано в двоичном виде, то нужно его переводить в десятичную систему(мне нужно число именно в десятичной системе). И даже уже начал писать код для перевода чисел, но потом остановился. Мне пришла мысль, что я изобретаю велосипед.
До меня все уже придумано. Либо есть есть стандартная функция, либо компилятор сам это сделает. Собственно поэтому и решил уточнить. Как оказалось, это было не зря!
[uquote="Martian",url="/forum/viewtopic.php?p=4490017#p4490017"]и вся запись будет
ADC_Result = ((unsigned short)(ADC_DRL << 8 )) | ADC_DRL;[/uquote]
Еще хотел уточнить. Вы случайно не допустили опечатку? Не вот так ли должна выглядеть конечная запись: ADC_Result = ((unsigned short)(ADC_DRH << 8 )) | ADC_DRL; Это если выравнивание по правому краю
А если по левому то вот так:
ADC_Result = ((unsigned short)(ADC_DRL >> 8 )) | ADC_DRH; ?
Обобщенно системы исчисления я знаю( я думаю, что знаю
[uquote="Martian",url="/forum/viewtopic.php?p=4490017#p4490017"]и вся запись будет
ADC_Result = ((unsigned short)(ADC_DRL << 8 )) | ADC_DRL;[/uquote]
Еще хотел уточнить. Вы случайно не допустили опечатку? Не вот так ли должна выглядеть конечная запись: ADC_Result = ((unsigned short)(ADC_DRH << 8 )) | ADC_DRL; Это если выравнивание по правому краю
А если по левому то вот так:
ADC_Result = ((unsigned short)(ADC_DRL >> 8 )) | ADC_DRH; ?
-
veso74
- Поставщик валерьянки для Кота
- Сообщения: 1905
- Зарегистрирован: Сб май 05, 2012 20:24:52
- Откуда: KN34PC, Болгария
- Контактная информация:
Re: Программирование STM8
Просто используйте готовую функцию:
которая делает то же самое, и уже сделана:
https://github.com/ZiB/STM8S-USB/blob/m ... dc1.c#L390
Код: Выделить всё
#include "stm8s_adc1.h"
...
ADC1_StartConversion();
while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == FALSE);
val = ADC1_GetConversionValue();
ADC1_ClearFlag(ADC1_FLAG_EOC);https://github.com/ZiB/STM8S-USB/blob/m ... dc1.c#L390
Re: Программирование STM8
да, верно, забыл исправить после копи-пасте наименования. Спасибо! Исправил.Pjatruha@mail.ru писал(а):допустили опечатку?
Добавлено after 22 minutes 17 seconds:
[uquote="veso74",url="/forum/viewtopic.php?p=4490139#p4490139"]Просто используйте готовую функцию:[/uquote]
можно просто написать
Код: Выделить всё
__near __no_init volatile unsigned short ADC1_DR @0x5344;-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
[uquote="veso74",url="/forum/viewtopic.php?p=4490139#p4490139"]которая делает то же самое, и уже сделана:
https://github.com/ZiB/STM8S-USB/blob/m ... dc1.c#L390[/uquote]
Спасибо за ссылку. Попробую разобраться. Но признаться честно, мне пока тяжело читать чужой код в силу нехватки знаний. Со словарем-то(с интернетом) я читаю, но очень долго
https://github.com/ZiB/STM8S-USB/blob/m ... dc1.c#L390[/uquote]
Спасибо за ссылку. Попробую разобраться. Но признаться честно, мне пока тяжело читать чужой код в силу нехватки знаний. Со словарем-то(с интернетом) я читаю, но очень долго
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Ранее написал программку для ЖКИ. Она работает без нареканий.
Перешел к изучению АЦП. Решил переписать представленную выше программу. На ЖКИ должно отображаться 3 старших знака максимального измеренного значения в милливольтах(например, 330, если значение равно 3300). Но по факту у меня какой-то мусор на ЖКИ.
Подскажите, пожалуйста, где я мог допустить ошибку?
Спойлер
Код: Выделить всё
#include "IOSTM8S103F3.h"
volatile int x=0, y=111, m=0;
volatile char i=1,j=0,n=0,k=1,L_1,L_2,L_3;
char ZNAK[8] =
{ //0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
1,0, 1,0, 1,0, 0,1 //7
};
char DIGIT[11][2][8] =
{
{ // 0
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 1,0, 0,1, 0,1} //t (1)
},
{ // 1
//1 2 3 4 5 6 7 8
//12 11 10 09
{1,0, 0,1, 0,1, 1,0}, //7 (0)
{1,0, 1,0, 1,0, 1,0} //t (1)
},
{ // 2
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 1,0, 1,0}, //7 (0)
{1,0, 0,1, 0,1, 0,1} //t (1)
},
{ // 3
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{1,0, 0,1, 1,0, 0,1} //t (1)
},
{ // 4
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{1,0, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 1,0, 1,0} //t (1)
},
{ // 5
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 1,0, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 1,0, 0,1} //t (1)
},
{ // 6
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 1,0, 0,1, 1,0}, //7 (1)
{0,1, 0,1, 0,1, 0,1} //t (0)
},
{ // 7
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{1,0, 1,0, 1,0, 1,0} //t (1)
},
{ // 8
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 0,1, 0,1} //t (1)
},
{ // 9
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 1,0, 0,1} //t (1)
},
{ // PUSTO
{1,0, 1,0, 1,0, 1,0}, //13 (0)
{1,0, 1,0, 1,0, 1,0} //14 (1)
},
};
void DELENIE()
{
L_3=y/100;
L_2=(y-(L_3*100))/10; //260-2*100=60
L_1=(y-(L_3*100))-(L_2*10); //(260-(2*100))-(6*10)
}
#pragma vector=TIM1_OVR_UIF_vector
__interrupt void TIM1_interrupt(void)
{
TIM1_SR1_bit.UIF = 0; //Cброс флага прерывания
k++;
if (k == 9)
{
k=1;
}
j=k-1;
if (m > 0)
{
m++;
if (m >= 25)
{
if ((PD_IDR_bit.IDR1 == 1) & (PB_IDR_bit.IDR4 == 1))
{
m = -25;
}
}
}
if (m < 0)
{
m++;
if (m == -1)
{
m = 0;
PB_CR2_bit.C24 = 1; // разрещаем прерывание
PD_CR2_bit.C21 = 1; // разрещаем прерывание
}
}
}
#pragma vector=EXTI1_vector //Кнопка "+"
__interrupt void PinB4_interrupt(void)
{
PB_CR2_bit.C24 = 0; // запрещаем прерывание
PD_CR2_bit.C21 = 0; // запрещаем прерывание
m=1;
y=y+5;
if (y >= 500)
{
y=500;
}
DELENIE();
}
#pragma vector=EXTI3_vector //Кнопка "-"
__interrupt void PinD2_interrupt(void)
{
PB_CR2_bit.C24 = 0; // запрещаем прерывание
PD_CR2_bit.C21 = 0; // запрещаем прерывание
m=1;
y=y-5;
if (y <= 100)
{
y=100;
}
DELENIE();
}
void com_D12()
{
PC_DDR_bit.DDR3 = 0; // Вход com D9
PC_CR1_bit.C13 = 0; // Подтягивающий резистор отключен
PC_ODR_bit.ODR6 = 1; // Высокий уровень на выходе
PC_CR1_bit.C16 = 1; // push-pull
PC_DDR_bit.DDR6 = 1; // Выход com D12
}
void com_D12_()
{
PC_ODR_bit.ODR6 = 0; // Низкий уровень на выходе com D12
}
void com_D11()
{
PC_DDR_bit.DDR6 = 0; // Вход com D12
PC_CR1_bit.C16 = 0; // Подтягивающий резистор отключен
PC_ODR_bit.ODR5 = 1; // Высокий уровень на выходе
PC_CR1_bit.C15 = 1; // push-pull
PC_DDR_bit.DDR5 = 1; // Выход com D11
}
void com_D11_()
{
PC_ODR_bit.ODR5 = 0; // Низкий уровень на выходе com D11
}
void com_D10()
{
PC_DDR_bit.DDR5 = 0; // Вход com D11
PC_CR1_bit.C15 = 0; // Подтягивающий резистор отключен
PC_ODR_bit.ODR4 = 1; // Высокий уровень на выходе
PC_CR1_bit.C14 = 1; // push-pull
PC_DDR_bit.DDR4 = 1; // Выход com D10
}
void com_D10_()
{
PC_ODR_bit.ODR4 = 0; // Низкий уровень на выходе com D10
}
void com_D9()
{
PC_DDR_bit.DDR4 = 0; // Вход com D10
PC_CR1_bit.C14 = 0; // Подтягивающий резистор отключен
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
PD_DDR_bit.DDR3 = 0; // Вход.Детектор нуля.
PD_CR1_bit.C13 = 1; // Подтягивающий резистор отключен
PD_CR2_bit.C23 = 0; // Прерывая разрещены
EXTI_CR1_bit.PDIS = 3; //прерывание по спаду и подъему фронта на всем порту 'D'
PD_DDR_bit.DDR4 = 0; // Вход.
PD_CR1_bit.C14 = 1; // Подтягивающий резистор подключен
PD_CR2_bit.C24 = 0; // Прерывая запрещены
PD_DDR_bit.DDR5 = 0; // Вход.
PD_CR1_bit.C15 = 1; // Подтягивающий резистор подключен
PD_CR2_bit.C25 = 0; // Прерывая запрещены
PB_DDR_bit.DDR4 = 0; // Вход. Кнопка "+"
PB_CR1_bit.C14 = 0; // Подтягивающий резистор отключен
PB_CR2_bit.C24 = 1; // Прерывая разрещены
EXTI_CR1_bit.PBIS = 3; //прерывание по спаду фронта на всем порту 'B'
PD_DDR_bit.DDR1 = 0; // Вход. Кнопка "-"
PD_CR1_bit.C11 = 1; // Подтягивающий резистор подключен
PD_CR2_bit.C21 = 1; // Прерывая разрещены
//EXTI_CR1_bit.PDIS = 3; //прерывание по спаду фронта
PC_DDR_bit.DDR3 = 0; // Вход com D9
PC_CR1_bit.C13 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C23 = 0; // Прерывая запрещены
PC_DDR_bit.DDR4 = 0; // Вход com D10
PC_CR1_bit.C14 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C24 = 0; // Прерывая запрещены
PC_DDR_bit.DDR5 = 0; // Вход com D11
PC_CR1_bit.C15 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C25 = 0; // Прерывая запрещены
PC_DDR_bit.DDR6 = 0; // Вход com D12
PC_CR1_bit.C16 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C26 = 0; // Прерывая запрещены
PC_DDR_bit.DDR7 = 1; // Выход SEG D13
PC_CR1_bit.C17 = 1; // push-pull
PC_CR2_bit.C27 = 0; // Cкорость переключения 2МГц
PD_DDR_bit.DDR2 = 1; // Выход SEG D14
PD_CR1_bit.C12 = 1;
PD_CR2_bit.C22 = 0;
PD_DDR_bit.DDR6 = 1; // Выход SEG D5
PD_CR1_bit.C16 = 1;
PD_CR2_bit.C26 = 0;
PA_DDR_bit.DDR1 = 1; // Выход SEG D6
PA_CR1_bit.C11 = 1;
PA_CR2_bit.C21 = 0;
PA_DDR_bit.DDR2 = 1; // Выход SEG D7
PA_CR1_bit.C12 = 1;
PA_CR2_bit.C22 = 0;
PA_DDR_bit.DDR3 = 1; // Выход SEG D8
PA_CR1_bit.C13 = 1;
PA_CR2_bit.C23 = 0;
PB_DDR_bit.DDR5 = 1; // Настройка 5-го бита порта B на вывод.
PB_ODR_bit.ODR5 = 1; // Гашение светодиода.
PB_CR1_bit.C15 = 1; // Переключение порта в режим push-pull.
PB_CR2_bit.C25 = 0; // Cкорость переключения до 2 МГц
//Частота переполнений = 16000000Гц / 32 / 500 = 1000 Гц(1 мс)
TIM1_PSCRH = 0x00;//записываем 2 старших байта числа 31(32-1) в hex формате в регистр предделителя
TIM1_PSCRL = 0x1F;//записываем 2 младших байта числа 31(32-1)в hex формате в регистр предделителя
TIM1_ARRH = 0x01; //записываем 2 старших байта числа 500 в hex формате в регистр автоперезагруски
TIM1_ARRL = 0xF4; //записываем 2 младших байта числа 500 в hex формате в регистр автоперезагруски
TIM1_CR1_bit.DIR = 0; // Cчет вверх
TIM1_CR1_bit.URS = 1; //Прерывание только по переполнению счетчика
TIM1_EGR_bit.UG = 1; //Вызываем Update Event для загрузки предделителя
TIM1_IER_bit.UIE = 1; //Разрешаем прерывание
TIM1_CR1_bit.CEN = 1; //Запускаем таймер
asm("rim");
DELENIE();
while(1)
{
SEG();
COM();
}
}
Спойлер
Код: Выделить всё
#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;
void DELENIE()
{
L_3=y/1000;//3300/1000=3
L_2=(y-(L_3*1000))/100; //3300-3*1000=300
L_1=(y-(L_3*1000))-(L_2*100); //(3300-(3*1000))-(3*100)
}
char ZNAK[8] =
{ //0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
1,0, 1,0, 1,0, 0,1 //7
};
char DIGIT[11][2][8] =
{
{ // 0
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 1,0, 0,1, 0,1} //t (1)
},
{ // 1
//1 2 3 4 5 6 7 8
//12 11 10 09
{1,0, 0,1, 0,1, 1,0}, //7 (0)
{1,0, 1,0, 1,0, 1,0} //t (1)
},
{ // 2
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 1,0, 1,0}, //7 (0)
{1,0, 0,1, 0,1, 0,1} //t (1)
},
{ // 3
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{1,0, 0,1, 1,0, 0,1} //t (1)
},
{ // 4
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{1,0, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 1,0, 1,0} //t (1)
},
{ // 5
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 1,0, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 1,0, 0,1} //t (1)
},
{ // 6
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 1,0, 0,1, 1,0}, //7 (1)
{0,1, 0,1, 0,1, 0,1} //t (0)
},
{ // 7
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{1,0, 1,0, 1,0, 1,0} //t (1)
},
{ // 8
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 0,1, 0,1} //t (1)
},
{ // 9
//0 1 2 3 4 5 6 7
//1 2 3 4 5 6 7 8
//12 11 10 09
{0,1, 0,1, 0,1, 1,0}, //7 (0)
{0,1, 0,1, 1,0, 0,1} //t (1)
},
{ // PUSTO
{1,0, 1,0, 1,0, 1,0}, //13 (0)
{1,0, 1,0, 1,0, 1,0} //14 (1)
},
};
#pragma vector=TIM1_OVR_UIF_vector
__interrupt void TIM1_interrupt(void)
{
TIM1_SR1_bit.UIF = 0; //Cброс флага прерывания
k++;
t++;
if (k == 9)
{
k=1;
}
j=k-1;
}
void com_D12()
{
PC_DDR_bit.DDR3 = 0; // Вход com D9
PC_CR1_bit.C13 = 0; // Подтягивающий резистор отключен
PC_ODR_bit.ODR6 = 1; // Высокий уровень на выходе
PC_CR1_bit.C16 = 1; // push-pull
PC_DDR_bit.DDR6 = 1; // Выход com D12
}
void com_D12_()
{
PC_ODR_bit.ODR6 = 0; // Низкий уровень на выходе com D12
}
void com_D11()
{
PC_DDR_bit.DDR6 = 0; // Вход com D12
PC_CR1_bit.C16 = 0; // Подтягивающий резистор отключен
PC_ODR_bit.ODR5 = 1; // Высокий уровень на выходе
PC_CR1_bit.C15 = 1; // push-pull
PC_DDR_bit.DDR5 = 1; // Выход com D11
}
void com_D11_()
{
PC_ODR_bit.ODR5 = 0; // Низкий уровень на выходе com D11
}
void com_D10()
{
PC_DDR_bit.DDR5 = 0; // Вход com D11
PC_CR1_bit.C15 = 0; // Подтягивающий резистор отключен
PC_ODR_bit.ODR4 = 1; // Высокий уровень на выходе
PC_CR1_bit.C14 = 1; // push-pull
PC_DDR_bit.DDR4 = 1; // Выход com D10
}
void com_D10_()
{
PC_ODR_bit.ODR4 = 0; // Низкий уровень на выходе com D10
}
void com_D9()
{
PC_DDR_bit.DDR4 = 0; // Вход com D10
PC_CR1_bit.C14 = 0; // Подтягивающий резистор отключен
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; // Прерывая запрещены
PD_DDR_bit.DDR4 = 0; // Вход.
PD_CR1_bit.C14 = 1; // Подтягивающий резистор подключен
PD_CR2_bit.C24 = 0; // Прерывая запрещены
PD_DDR_bit.DDR5 = 0; // Вход.
PD_CR1_bit.C15 = 1; // Подтягивающий резистор подключен
PD_CR2_bit.C25 = 0; // Прерывая запрещены
PC_DDR_bit.DDR3 = 0; // Вход com D9
PC_CR1_bit.C13 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C23 = 0; // Прерывая запрещены
PC_DDR_bit.DDR4 = 0; // Вход com D10
PC_CR1_bit.C14 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C24 = 0; // Прерывая запрещены
PC_DDR_bit.DDR5 = 0; // Вход com D11
PC_CR1_bit.C15 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C25 = 0; // Прерывая запрещены
PC_DDR_bit.DDR6 = 0; // Вход com D12
PC_CR1_bit.C16 = 0; // Подтягивающий резистор отключен
PC_CR2_bit.C26 = 0; // Прерывая запрещены
PC_DDR_bit.DDR7 = 1; // Выход SEG D13
PC_CR1_bit.C17 = 1; // push-pull
PC_CR2_bit.C27 = 0; // Cкорость переключения 2МГц
PD_DDR_bit.DDR2 = 1; // Выход SEG D14
PD_CR1_bit.C12 = 1;
PD_CR2_bit.C22 = 0;
PD_DDR_bit.DDR6 = 1; // Выход SEG D5
PD_CR1_bit.C16 = 1;
PD_CR2_bit.C26 = 0;
PA_DDR_bit.DDR1 = 1; // Выход SEG D6
PA_CR1_bit.C11 = 1;
PA_CR2_bit.C21 = 0;
PA_DDR_bit.DDR2 = 1; // Выход SEG D7
PA_CR1_bit.C12 = 1;
PA_CR2_bit.C22 = 0;
PA_DDR_bit.DDR3 = 1; // Выход SEG D8
PA_CR1_bit.C13 = 1;
PA_CR2_bit.C23 = 0;
PB_DDR_bit.DDR5 = 1; // Настройка 5-го бита порта B на вывод.
PB_ODR_bit.ODR5 = 1; // Гашение светодиода.
PB_CR1_bit.C15 = 1; // Переключение порта в режим push-pull.
PB_CR2_bit.C25 = 0; // Cкорость переключения до 2 МГц
//Частота переполнений = 16000000Гц / 32 / 500 = 1000 Гц(1 мс)
TIM1_PSCRH = 0x00;//записываем 2 старших байта числа 31(32-1) в hex формате в регистр предделителя
TIM1_PSCRL = 0x1F;//записываем 2 младших байта числа 31(32-1)в hex формате в регистр предделителя
TIM1_ARRH = 0x01; //записываем 2 старших байта числа 500 в hex формате в регистр автоперезагруски
TIM1_ARRL = 0xF4; //записываем 2 младших байта числа 500 в hex формате в регистр автоперезагруски
TIM1_CR1_bit.DIR = 0; // Cчет вверх
TIM1_CR1_bit.URS = 1; //Прерывание только по переполнению счетчика
TIM1_EGR_bit.UG = 1; //Вызываем Update Event для загрузки предделителя
TIM1_IER_bit.UIE = 1; //Разрешаем прерывание
TIM1_CR1_bit.CEN = 1; //Запускаем таймер
i=1000; //временная задержка
do {i--;}
while (i>1);
ADC_CR1_bit.ADON=1; //повторная запись единицы дает команду на старт преобразования
asm("rim");
DELENIE();
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=x*3300000/1023;
DELENIE();
}
ADC_CR1_bit.ADON=1; // запускаем преобразование
}
}
}
-
veso74
- Поставщик валерьянки для Кота
- Сообщения: 1905
- Зарегистрирован: Сб май 05, 2012 20:24:52
- Откуда: KN34PC, Болгария
- Контактная информация:
Re: Программирование STM8
Логику кода не рассматривал, но на "первый взгляд::
Нужен результат в микровольтах?? Переведите формулу в милливольт.
Даже в милливольт, y в умножении далеко из граници unsigned short.
(Eсли компилятор не делает) может использовать temp переменную более высокой разрядности и последующее casting после деления для y.
Установите задержку после отображения.
void DELENIE() -> попробуйте с %:
Код: Выделить всё
y=x*3300000/1023;Даже в милливольт, y в умножении далеко из граници unsigned short.
(Eсли компилятор не делает) может использовать temp переменную более высокой разрядности и последующее casting после деления для y.
Код: Выделить всё
unsigned long tmp = x * 3300;
tmp /= 1023;
y = (unsigned short)tmp;void DELENIE() -> попробуйте с %:
Код: Выделить всё
L_3 = y / 1000;
L_2 = (y / 100) % 10;
L_1 = (y / 10) % 10;
Последний раз редактировалось veso74 Ср окт 18, 2023 21:52:51, всего редактировалось 1 раз.
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Да, ошибся нулями. Точнее сказать, забыл стереть после экспериментов. Но проблема не в этом. Даже если я явно присвою 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; // запускаем преобразование
}
}
-
veso74
- Поставщик валерьянки для Кота
- Сообщения: 1905
- Зарегистрирован: Сб май 05, 2012 20:24:52
- Откуда: KN34PC, Болгария
- Контактная информация:
Re: Программирование STM8
Поменяйте L_3, L_2, L_1 на:
В противном случае:
Код: Выделить всё
L_3 = y / 1000;
L_2 = (y / 100) % 10;
L_1 = (y / 10) % 10;Код: Выделить всё
L_3=y/1000;
L_2=(y-(L_3*1000))/100;
L_1=(y-(L_3*1000))-(L_2*100);
y = 111;
L_3 = 111 / 1000 = 0;
L_2 = (111 - (L_3 * 1000)) / 100 = (111 - 0) / 100 = 1;
L_1 = (111 - (0 * 1000)) - (1 * 100) = 111 - 100 = 11 ??? -> мусор-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Сделал правки по вашим советам и оно заработало! Но только если y присвоить явное число.
Если написать вот так
и на 4 вход ацп подать(даже можно не подавать) 3.3 вольта или нуль вольт, то на индикаторе отображается ␣28
Если написать вот так
Код: Выделить всё
if (x>y)
{
y=x;
DELENIE();
}Re: Программирование STM8
что это вообще? термометр?
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Re: Программирование STM8
ну, так ему точность ведь 1 градус более чем нормально?
-
Pjatruha@mail.ru
- Грызет канифоль
- Сообщения: 259
- Зарегистрирован: Пн фев 10, 2014 19:40:03
Re: Программирование STM8
Да. Но за точноть я пока не топлю.
Пока только изучаю ацп.