Доброго вечора. Проект цей доволі старий, тому реалізований був на Атмега8А. Проект передраний з другого контролера, який на тому підприємстві був встановлений. В квадратурного енкодера було використано тільки по одній ножці . Тобто даний контролер "не бачить" напрямку руху, і не бачить помилок енкодера при його поломці. Код виглядає так:
По одному каналу переривання ми зменшуємо амплітуду ЦАП:
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
  dp=1;
  if(step_dac)
  {
      if(step_dac>=step_dac_dn)
      {
       step_dac=step_dac-step_dac_dn;
      }
      else if(step_dac){ step_dac=0; }
  }
  if(step_dac<0)step_dac=0;
  timer_cnt=0; timer_res=0; // reset cnt data
}
По другому каналу переривання (другий енкодер) , ми збільшуємо амплітуду ЦАП:
// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here
  dp1=1;
  if(step_dac<4095)step_dac=step_dac+step_dac_up;
  if(step_dac>4095)step_dac=4095;
}
ЦАП у нас 12 біт, тому відлік в діапазоні від 0 до 4095. Це дорівнює значенню напруги на виході вже ОУ (після підсилення): від 0 до 10В.
Ідея зміщення різки цегли заключається в корекції амплітуди ЦАП (множення на коефіцієнт, який програмується з меню). Такий алгоритм дозволяє регулювати товщину цегли з кроком 10мм. А хочеться зробити точніше....
Програмування коефіцієнта з меню:
if(menu==2)
    {        
       if(PLUS==0 && MINUS)
       {
        if(timer_button==0){if(step_dac_up<999)step_dac_up++; }
        if(++timer_button>45){timer_button=42; if(step_dac_up<999)step_dac_up++;}
        flags_butt=1;
       }
       else if(MINUS==0 && PLUS) 
       {
        if(timer_button==0){if(step_dac_up>1)step_dac_up--; }
        if(++timer_button>45){ timer_button=42; if(step_dac_up>1)step_dac_up--; } 
        flags_butt=1;
       }
       led_buff[3]=led_table[23];
       led_out(step_dac_up);
    }
    else if(menu==1)
    {
      if(PLUS==0 && MINUS)
       {
        if(timer_button==0){if(step_dac_dn<999)step_dac_dn++; }
        if(++timer_button>45){timer_button=42; if(step_dac_dn<999)step_dac_dn++;}
        flags_butt=1;
       }
       else if(MINUS==0 && PLUS) 
       {
        if(timer_button==0){if(step_dac_dn>1)step_dac_dn--; }
        if(++timer_button>45){ timer_button=42; if(step_dac_dn>1)step_dac_dn--; } 
        flags_butt=1;
       }
       led_buff[3]=led_table[13];
       led_out(step_dac_dn);
    }
Оновлення даних відбувається в головному циклі так:
if(step_dac!=step_dac_buff)
       {
        SPI_MCP4921(step_dac);
        step_dac_buff=step_dac;
        timer_ovf=390; 
       }
Код вивода даних в ЦАП:
// === SPI DAC ======//
#define CLK PORTB.2
#define DATA PORTB.3
#define CS PORTB.4
void SPI_MCP4921(unsigned int data) // DAC
{
 unsigned int mask=0b1000000000000000;
 char x=0; 
 
 data = data | 0x3000; 
  CS=0;
  delay_us(1); 
 for(x=0; x<16; x++)
 { 
   
   if(data&mask) DATA=1;
   else DATA=0;
   delay_us(1);
    CLK=1;
   delay_us(1); 
    CLK=0; 
   delay_us(1);  
     mask>>=1;
 }
   delay_us(1); 
   CS=1;
}
Принципова схема пристроя:
https://drive.google.com/file/d/1S9SVnz … sp=sharing