Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Программирование STM8

Ср окт 04, 2023 20:51:05

у меня используется в функциях и прерываниях без volatile и прекрасно работает. Но я не использую оптимизатор, или, если использую, смотрю, что он там наоптимизировал.

Re: Программирование STM8

Ср окт 04, 2023 20:55:53

Мне тоже кажется, что проблема в этих настройках:
Изображение

Re: Программирование STM8

Ср окт 04, 2023 21:01:16

ну, не совсем в них :) Вам просто надо изучить тонкости оптимизатора, методы отладки и всё будет норм.
Потом станет привычным. Если бы VladislavS не сказал, я бы и не вспомнил про оптимизатор.

Re: Программирование STM8

Ср окт 04, 2023 21:24:08

Правильно ли я понял, что его обязательно нужно применять при программировании любых МК, если переменная используется(читай меняет свое значение) в функциях и прерываниях?
Для простоты считайте, что это так.

Добавлено after 7 minutes 46 seconds:
Мне тоже кажется, что проблема в этих настройках:
Проблемы в этих настройках, конечно же, нет. Оптимизация должна быть включена, чтобы код был быстрым или компактным. Проблема в том, что нужно представлять что делает оптимизатор и выполнять минимальные требования при написании кода. Их не очень много, но на одно из них вы наступили. В следующий раз учтёте уже.

Re: Программирование STM8

Ср окт 04, 2023 21:50:22

VladislavS
Такое я точно не забуду. :) Компилятор из переменной делает константу... :shock: Скажи мне кто раньше об этом - ни за что не поверил бы.

Re: Программирование STM8

Вт окт 17, 2023 01:20:21

Перешел к изучению АЦП в STM8S. Подскажите, пожалуйста, правильно ли я понимаю, что результат преобразования АЦП будет записан в регистры ADC_DRL и ADC_DRH в двоичной системе исчисления? Если это так, то как перевести результат преобразования в десятичную систему исчисления и присвоить его переменной?

Re: Программирование STM8

Вт окт 17, 2023 01:59:18

Это условности, всё в этом электронном мире в двоичной системе.
Но вообще, системы счисления изучают до программирования, Вы обязаны знать как минимум ещё две: двоичную и шестнадцатеричную. И будет лучше, если прочитаете про них в книжке.
Но в кратце: указанные Вами регистры состоят из битов, 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 MiB) Скачиваний: 22
Последний раз редактировалось Martian Вт окт 17, 2023 13:29:48, всего редактировалось 1 раз.

Re: Программирование STM8

Вт окт 17, 2023 09:22:13

Большое спасибо за ответ. А за книжечку отдельная благодарность.
Обобщенно системы исчисления я знаю( я думаю, что знаю :) ). С книжкой обязательно ознакомлюсь. Если ничего нового не узнаю, то как минимум освежу знания. В принципе, так как вы сказали, так я все это и понимал. Единственное, думал, раз число записано в двоичном виде, то нужно его переводить в десятичную систему(мне нужно число именно в десятичной системе). И даже уже начал писать код для перевода чисел, но потом остановился. Мне пришла мысль, что я изобретаю велосипед. :)) До меня все уже придумано. Либо есть есть стандартная функция, либо компилятор сам это сделает. Собственно поэтому и решил уточнить. Как оказалось, это было не зря! :)
и вся запись будет
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; ?

Re: Программирование STM8

Вт окт 17, 2023 10:28:59

Просто используйте готовую функцию:
Код:
#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

Вт окт 17, 2023 13:53:13

Pjatruha@mail.ru писал(а):допустили опечатку?
да, верно, забыл исправить после копи-пасте наименования. Спасибо! Исправил.

Добавлено after 22 minutes 17 seconds:
Просто используйте готовую функцию:

можно просто написать
Код:
__near __no_init volatile unsigned short ADC1_DR @0x5344;

и никаких функций ;)

Re: Программирование STM8

Вт окт 17, 2023 20:57:42

которая делает то же самое, и уже сделана:
https://github.com/ZiB/STM8S-USB/blob/m ... dc1.c#L390

Спасибо за ссылку. Попробую разобраться. Но признаться честно, мне пока тяжело читать чужой код в силу нехватки знаний. Со словарем-то(с интернетом) я читаю, но очень долго :)

Re: Программирование STM8

Ср окт 18, 2023 21:12:30

Ранее написал программку для ЖКИ. Она работает без нареканий.
Спойлер
Код:
#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();
  }
}


Перешел к изучению АЦП. Решил переписать представленную выше программу. На ЖКИ должно отображаться 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;

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; // запускаем преобразование
    }
  }
}

Изображение Изображение Изображение Изображение Изображение

Подскажите, пожалуйста, где я мог допустить ошибку?

Re: Программирование STM8

Ср окт 18, 2023 21:32:19

Логику кода не рассматривал, но на "первый взгляд::
Код:
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 раз.

Re: Программирование STM8

Ср окт 18, 2023 21:50:37

Да, ошибся нулями. Точнее сказать, забыл стереть после экспериментов. Но проблема не в этом. Даже если я явно присвою 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; // запускаем преобразование
    }
  }

Изображение

Re: Программирование STM8

Ср окт 18, 2023 22:07:25

Поменяйте 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 ??? -> мусор

Re: Программирование STM8

Ср окт 18, 2023 23:00:29

Сделал правки по вашим советам и оно заработало! Но только если y присвоить явное число.
Если написать вот так
Код:
 if (x>y)
    {
          y=x;
          DELENIE();
    }

и на 4 вход ацп подать(даже можно не подавать) 3.3 вольта или нуль вольт, то на индикаторе отображается ␣28

Re: Программирование STM8

Ср окт 18, 2023 23:05:31

что это вообще? термометр?

Re: Программирование STM8

Ср окт 18, 2023 23:07:01

:) Почти. Паяльник.

Re: Программирование STM8

Ср окт 18, 2023 23:11:28

ну, так ему точность ведь 1 градус более чем нормально?

Re: Программирование STM8

Ср окт 18, 2023 23:15:48

Да. Но за точноть я пока не топлю. :) Пока только изучаю ацп.
Ответить