как вывести младший байт в порт

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

как вывести младший байт в порт

Сообщение novarobotix »

надо уменьшить время выполнения операции в программе. есть код:

PORTD.0=0;
PORTD.1=1;
PORTD.2=1;
PORTD.3=0;

можно ли эти 4 операции свести к одной? типа:
PORTDL=6;

то есть вывести одной командой первые 4 ноги порта а вторые 4 не трогать
Глупый не задает вопросы. Глупый и так все знает.
mas123
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Re: как вывести младший байт в порт

Сообщение mas123 »

novarobotix писал(а):PORTDL=6;
Если у контроллера есть такой "регистр", то можно. В даташите не описано? Значит нельзя. 8)

Тут только вариант "чтение - модификация - запись".
Читаешь из порта в регистр, накладываешь маску по AND, добавляешь биты по OR и пишешь обратно в порт.

Либо переделываешь схему! Так чтобы старший полубайт (не байт, как в топике!) ничем не использовался или использовался как вход, или как альтернативная функция.
И тогда пиши смело в PORTD что угодно от 0x00 до 0x0F - одной командой поменяешь все 4 бита.
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: как вывести младший байт в порт

Сообщение uk8amk »

Очень сомнительная экономия.
Поразрядный вывод, 4 инструкции:

Код: Выделить всё

   CBI  0x12,0
;      48 PORTD.1=1;
   SBI  0x12,1
;      49 PORTD.2=1;
   SBI  0x12,2
;      50 PORTD.3=0;
   CBI  0x12,3


Жертвуем старшей тетрадой, 2 инструкции:

Код: Выделить всё

;      52 PORTD = 0x06;
   LDI  R30,LOW(6)
   OUT  0x12,R30


Чтение-модификация-запись, ещё хуже:

Код: Выделить всё

;      54 PORTD &= ~0x0F;
   IN   R30,0x12
   ANDI R30,LOW(0xF0)
   OUT  0x12,R30
;      55 PORTD |= 0x06;
   IN   R30,0x12
   ORI  R30,LOW(0x6)
   OUT  0x12,R30


Что выиграли?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: как вывести младший байт в порт

Сообщение ARV »

uk8amk писал(а):Что выиграли?

ну, если бы вы написали действительно корректную запись чтения-модификации, то результат был бы чуток получше:

Код: Выделить всё

PORTD = PORTD & 0xF0 | 0x06;

результат:

Код: Выделить всё

IN        R24,0x12       In from I/O location
ANDI      R24,0xF0       Logical AND with immediate
ORI       R24,0x06       Logical OR with immediate
OUT       0x12,R24 
выигрыш будет более заметным, если от "ручной установки битов" будет сделан переход к "установке по битам переменной" либо количество битов станет больше 4-х. главное правильный подход.

P.S. и вообще, речь фактически идет о выводе младшей тетрады, а не младшего байта :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

у меня сейчас такой код

Спойлер

Код: Выделить всё

//начало  обработки шагов 
             
if (step==1 & go_step==1)
 {             
 go_step=0;
    PORTC.1=1;
    PORTC.2=0;
    PORTC.3=0;
    PORTC.4=0; 
  }
 
if (step==2 & go_step==1) 
 { go_step=0;
    PORTC.1=1;
    PORTC.2=1;
    PORTC.3=0;
    PORTC.4=0; 
  }
 
  if (step==3 & go_step==1)
 {go_step=0;           
    PORTC.1=0;
    PORTC.2=1;
    PORTC.3=0;
    PORTC.4=0; 
  }
 
  if (step==4 & go_step==1)
 {go_step=0;
    PORTC.1=0;
    PORTC.2=1;
    PORTC.3=1;
    PORTC.4=0; 
  }
   
  if (step==5 & go_step==1)
 { go_step=0;             
    PORTC.1=0;
    PORTC.2=0;
    PORTC.3=1;
    PORTC.4=0; 
  }
 
    if (step==6 & go_step==1)
 { go_step=0;
    PORTC.1=0;
    PORTC.2=0;
    PORTC.3=1;
    PORTC.4=1; 
  } 
 
    if (step==7 & go_step==1)
 { go_step=0;             
    PORTC.1=0;
    PORTC.2=0;
    PORTC.3=0;
    PORTC.4=1; 
  }
 
      if (step==8 & go_step==1)
 { go_step=0;
    PORTC.1=1;
    PORTC.2=0;
    PORTC.3=0;
    PORTC.4=1; 
  }

хочу заменить на предварительную запись 8 чисел в массив к примеру a[1]=6 a[2]=8 и так 8 раз для каждого шага соответствующая цифра
и потом вызывать в программе вместо всей той бандуры что привёл сверху
одной строкой:

Код: Выделить всё

PORTC=a[step]
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Re: как вывести младший байт в порт

Сообщение oleg110592 »

AVR446: Linear speed control of stepper motor on tinyAVR and megaAVR:

Код: Выделить всё

#define SM_PORT         PORTD
#define SM_DRIVE        DDRD
#define A1    PD7 //!< Stepper motor winding A positive pole.
#define A2    PD6 //!< Stepper motor winding A negative pole.
#define B1    PD5 //!< Stepper motor winding B positive pole.
#define B2    PD4 //!< Stepper motor winding B negative pole.
....

// Bit position for data in step table
#define BIT_A1 3
#define BIT_A2 2
#define BIT_B1 1
#define BIT_B2 0

//! Table with control signals for stepper motor
__flash unsigned char steptab[] = {((1<<BIT_A1) | (0<<BIT_A2) | (0<<BIT_B1) | (0<<BIT_B2)),
                                   ((1<<BIT_A1) | (0<<BIT_A2) | (1<<BIT_B1) | (0<<BIT_B2)),
                                   ((0<<BIT_A1) | (0<<BIT_A2) | (1<<BIT_B1) | (0<<BIT_B2)),
                                   ((0<<BIT_A1) | (1<<BIT_A2) | (1<<BIT_B1) | (0<<BIT_B2)),
                                   ((0<<BIT_A1) | (1<<BIT_A2) | (0<<BIT_B1) | (0<<BIT_B2)),
                                   ((0<<BIT_A1) | (1<<BIT_A2) | (0<<BIT_B1) | (1<<BIT_B2)),
                                   ((0<<BIT_A1) | (0<<BIT_A2) | (0<<BIT_B1) | (1<<BIT_B2)),
                                   ((1<<BIT_A1) | (0<<BIT_A2) | (0<<BIT_B1) | (1<<BIT_B2))};

void sm_driver_StepOutput(unsigned char pos)
{
  unsigned char temp = steptab[pos];
  // Output the fast way
  SM_PORT |= ((temp<<4)&0xF0);
  SM_PORT &= ((temp<<4)|0x0F);
}
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

ассемблер это хорошо, но я пишу на си под atmega16
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: как вывести младший байт в порт

Сообщение Аlex »

Причём тут ассемблер ? :facepalm:
Что можно объяснить человеку, который даже не знает что такое байт :)))
novarobotix, начните с азов. А конкретно - байт, бит, логические операции, дальше - цифровая электроника. А потом уже садитесь за книгу по языку.
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

да, ошибся, не младший байт а младшие пол байта.
но смысл понятен, я подробно расписал что нужно.
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
eess9
Вымогатель припоя
Сообщения: 672
Зарегистрирован: Ср фев 29, 2012 01:58:32
Откуда: Харьков, Украина

Re: как вывести младший байт в порт

Сообщение eess9 »

Аlex писал(а):Причём тут ассемблер ? :facepalm:
novarobotix, начните с азов. А конкретно - байт, бит, логические операции, дальше - цифровая электроника. А потом уже садитесь за книгу по языку.

А что мало было ассемблерного кода выше по теме? Или вы его в упор не видите?
novarobotix является радиолюбителем и знает ровно столько, сколько ему на сегодня надо (равно как и любой другой человек). Новое постигается по мере необходимости. Зачем за некорректную терминологию пинать человека ногами?
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

я вот думаю на первые 4 ноги порта выводить команды на мотор а вторые 4 ноги порта на ввод(к примеру читать степдир импульсы), но терзают смутные сомнения. если я сконфигурю вторые 4 ноги на ввод и сначала командой

Код: Выделить всё

PORTC=6 
я выведу на порт число а потом буду слушать не пришол ли сигнал на ногу порта которая сконфигурена на ввод

Код: Выделить всё

if (PIND.6==0) {dir=1;} //читаем направление 

повлияет ли то что я перед этим на весь порт вывел?
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: как вывести младший байт в порт

Сообщение zero648 »

Думаю не повлияет, если поставите внешние подтягивающие резисторы на входы.
mas123
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Re: как вывести младший байт в порт

Сообщение mas123 »

novarobotix писал(а):повлияет ли то что я перед этим на весь порт вывел?
А что об этом говорит даташит на atmega16?

Если не ошибаюсь, то оный рассказывает только о подтягивающих резисторах, подключение которых зависит от записи в порт в режиме "нога на чтение".
Итого: в целом может повлиять (при "особенностях" схемы). Но, если в старший полубайт писать всё время одно и то же - то не повлияет.
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

mas123 писал(а):Но, если в старший полубайт писать всё время одно и то же - то не повлияет.

какая разница одно и то же пишется или нет? либо влияет либо нет
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: как вывести младший байт в порт

Сообщение ARV »

да, разницы нет никакой, если изучить аппаратную часть и работать с ней корректно.
как известно, направление пинов порта вы задаете регистром DDRx. те пины, для которых в этом регистре установлены единицы, работают на вывод, т.е. будут "мощно" повторять те сигналы, которые вы пишите в PORTx. если же в DDRx для пинов заданы нолики, то эти пины будут работать на ввод, а соответствующие разряды PORTx будут либо включать встроенную подтяжку к плюсу, либо отключать ее.

поэтому для пинов, которые работают на ввод, вы обязаны всегда выводить в PORTx те же самые уровни, что там были до этого - в этом случае ничего не изменится.

итак, у вас старшие 4 бита работают на ввод, а младшие на вывод. чтобы никогда не менять состояние старших, вы должны делать так:

Код: Выделить всё

// это маска старшей тетрады. изменяя ее вы можете изменть назначение пинов в порту
#define HI_VAL 0xF0

// это маска младшей тетрады
#define LO_VAL (~HI_VAL)

// это режимы работы старшей тетрады порта
#define HI_MODE 0x80 /* пусть на старшем включена подтяжка, а на остальных - нет */

unsigned char lo_val; // а эта переменная будет у вас содержать выводимые на 4 младших пина сигналы

// нижеследующий код настраивает порт в соответствии с вашими предпочтениями
DDRD = LO_VAL;
PORTD = HI_VAL;

// нижеследующий код обновляет состояние младших 4 битов в порту, не затрагивая старшие
PORTD = HI_VAL | (lo_val & LO_VAL);


как-то так...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

я пока решил не заморачиваться с подтягивающими резисторами и прочими тонкостями, сделал просто и топорно
вот весь код
Спойлер

Код: Выделить всё

#include <io.h>    // Хотим использовать порты ввода/вывода
#include <delay.h>  // Хотим использовать функции задержек
#include <math.h>
#include <string.h>
#include <stdlib.h>



int step=1,temp_step,i,dir,temp,temp_save,step2=1,temp_step2,dir2,temp2,temp_save2,go_step,go_step2,c_on=1,ob,ob_temp,ob_const,c0,corr_count,mig_count,temp_mig_count,correct,cd;
unsigned long int  n,k,n2,k2,nfp,nfp2;
unsigned char a[9];

unsigned long int n_prev;
//int p;

eeprom unsigned long int n_eprom,n_eprom2,ob_eprom;


void mig(int v) {
                                       
for (i=0; i < v; i++)    {     //моргаем
PORTB.2=0; delay_us(100000);PORTB.2=1;delay_us(100000);PORTB.2=0;
   }
}



void main()

{
  DDRA=(0<<DDA7) | (0<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
  DDRB=(1<<DDB7) | (1<<DDB6) | (1<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);

a[1]=1;a[2]=3;a[3]=2;a[4]=6;a[5]=4;a[6]=12;a[7]=8;a[8]=9;

PORTA.0=1; // нормальное питание
nfp=n_eprom;
nfp=47; //вручную задаём момент включения кандёров
nfp2=n_eprom2;


while (1)
  {
  if (mig_count>0) temp_mig_count=temp_mig_count+1;
  if (mig_count>0 & temp_mig_count==500) {PORTB.1=0;} //моргаем число пропусков
  if (mig_count>0 & temp_mig_count==1000) {PORTB.1=1;mig_count=mig_count-1;temp_mig_count=0;}

  if (PINB.3==1){ob_temp=0;}
  if (PINB.3==0 & ob_temp==0 & ob>100 & dir==1){
  if (c0==1){
  corr_count=ob-400;
  if (abs(corr_count)>0) {correct=correct+corr_count;cd=0;mig_count=abs(correct);}  //PORTB.1=1;mig_count=mig_count+abs(abs(corr_count)/2);
             }
             ob_temp=1;
             ob=0;
             c0=1;
  } 
 
 
   if (k>100 || dir==2) cd=1;
 
  if (PINB.0==1 & temp_save==0) {n_eprom=n;nfp=n;temp_save=1;mig(2);} // записываем в память значение включения конденсаторов
  if (PINB.0==0) {temp_save=0;}  // nfp - значение с которого включаются кандёры X
  n2=5;
  if (PINB.4==1 & temp_save2==0) {n_eprom2=n2;nfp2=n2;temp_save2=1;mig(2);} // записываем в память значение включения конденсаторов для Y
  if (PINB.4==0) {temp_save2=0;}   // nfp2 - для Y

 
 
   /////////////////////////////////////////////// канал Х ......................
  if (PINC.5==0) {dir=1;} //читаем направление
  if (PINC.5==1) {dir=2;}

  if (PINC.4==0) {temp_step=0;}  //читем шаг
  if (PINC.4==1 & temp_step==0) {

   if (nfp>k+2) {
   PORTD.0=0; //индицируем выключение кандёров
   PORTD.2=0; //выключаем кандёры
   }
 
  PORTB.2=0; //индицируем отключение простоя
  go_step=1;     // пойдём делать шаг 
  temp_step=1;
  n=k;k=0; // обнуляем счётчик и узнаём время между импульсами n
 
  if (correct>=0 || cd==0) {  // шаг в одну сторону
  if (step==8 & dir==1) {step=1;temp=1;ob=ob+1;};
  if (step<8 & dir==1 & temp==0) {
  step++;temp=1;ob=ob+1;
 }
 }
 if(dir==1 & correct<0 & cd==1) correct++;
 
  if (correct<=0)     { // шаг в другую сторону
  if (step>1 & dir==2 & temp==0) {
  step--;temp=1;ob=ob-1;
  }
  if (step==1 & dir==2 & temp==0) {step=8;temp=1;ob=ob-1;}
  }
                   
 if(dir==2 & correct>0) correct--;
 
  temp=0;
  if (ob==-400) ob=0; 
     
  }
 
   
if (  nfp<n-2 ) {
   PORTD.0=1;  //индицируем включение кандёров
   PORTD.2=1; //включаем кандёры
 }
 
  if (k>5000)   //режим простоя
  {   
  PORTB.2=1; //индицируем  режим простоя
    PORTC=0;
  //PORTC.1=0;  //отключаем обмотки
 // PORTC.2=0;
//  PORTC.3=0;
//  PORTC.4=0;
 }
 

 
 
               //начало  обработки шагов 
if (go_step==1)  {PORTC=a[step];go_step=0;}             
               
/*             
if (step==1 & go_step==1)
 {             
 go_step=0;
    PORTC.1=1;
    PORTC.2=0;
    PORTC.3=0;
    PORTC.4=0; 
  }
 
if (step==2 & go_step==1) 
 { go_step=0;
    PORTC.1=1;
    PORTC.2=1;
    PORTC.3=0;
    PORTC.4=0; 
  }
 
  if (step==3 & go_step==1)
 {go_step=0;           
    PORTC.1=0;
    PORTC.2=1;
    PORTC.3=0;
    PORTC.4=0; 
  }
 
  if (step==4 & go_step==1)
 {go_step=0;
    PORTC.1=0;
    PORTC.2=1;
    PORTC.3=1;
    PORTC.4=0; 
  }
   
  if (step==5 & go_step==1)
 { go_step=0;             
    PORTC.1=0;
    PORTC.2=0;
    PORTC.3=1;
    PORTC.4=0; 
  }
 
    if (step==6 & go_step==1)
 { go_step=0;
    PORTC.1=0;
    PORTC.2=0;
    PORTC.3=1;
    PORTC.4=1; 
  } 
 
    if (step==7 & go_step==1)
 { go_step=0;             
    PORTC.1=0;
    PORTC.2=0;
    PORTC.3=0;
    PORTC.4=1; 
  }
 
      if (step==8 & go_step==1)
 { go_step=0;
    PORTC.1=1;
    PORTC.2=0;
    PORTC.3=0;
    PORTC.4=1; 
  }

*/ 
 
   
if (k<1000000) k=k+1;
if (k2<1000000) k2=k2+1; 
 
}
 
   
}

тут кроме самого степдира ещё сделано подключение сглаживающих кандёров на низких скоростях и энкодер для коррекции пропусков, но вроде работает.

настроил первые 4 на выход вторые 4 на вход

Код: Выделить всё

DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
на 4 и 5 пин подпаял степдирсигналы
задал табличку для вывода на порт младшего полубайта

Код: Выделить всё

a[1]=1;a[2]=3;a[3]=2;a[4]=6;a[5]=4;a[6]=12;a[7]=8;a[8]=9;
ну и сам вывод одной строкой

Код: Выделить всё

if (go_step==1)  {PORTC=a[step];go_step=0;} 

в результате общее время выполнения сократилось в полтора раза, учитывая большой остальной код разница существенная. ну и упрощать есть ещё что :))) у меня есть такое подозрение что скорость также зависит от размера переменной, типа операции с longint выполняются дольше чем с int
в ассемблерный код я попытался въехать, но пока туго, мозги в трубочку сворачиваются :dont_know:
Глупый не задает вопросы. Глупый и так все знает.
mas123
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Re: как вывести младший байт в порт

Сообщение mas123 »

novarobotix писал(а):я пока решил не заморачиваться с подтягивающими резисторами и прочими тонкостями, сделал просто и топорно
Именно что топорно.
novarobotix писал(а):что скорость также зависит от размера переменной,
Открой для себя чудесный мир оптимизации :))
Мало того, что размер переменной влияет, так ещё влияет и качество написания кода.
Зачем переменные с именем "step***" имеют тип int, если принимают значения куда меньше 0xFF, т.е. идеально укладываются в байт?
novarobotix писал(а):в ассемблерный код я попытался въехать, но пока туго
Очень сильно советую "въехать". Не нужен уровень "могу на асме написать что угодно", достаточно понимать что компилятор из твоего С-исходника сделал и понимать как быстро это работает и где тормозит.
novarobotix писал(а):if (abs(corr_count)>0)
Если абсолютное значение больше нуля.... Я правильно понимаю, что это замедленная запись if( 0 != corr_count ) ?
novarobotix писал(а):if (mig_count>0) temp_mig_count=temp_mig_count+1;
if (mig_count>0 & temp_mig_count==500) {PORTB.1=0;} //моргаем число пропусков
if (mig_count>0 & temp_mig_count==1000) {PORTB.1=1;mig_count=mig_count-1;temp_mig_count=0;}
Вот просто попробуй себя в роли процессора: три раза подряд проверить: "а вдруг mig_count больше нуля"?
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

mas123 писал(а):Если абсолютное значение больше нуля.... Я правильно понимаю, что это замедленная запись if( 0 != corr_count ) ?
:))) поржал с себя. да, неподумал

mas123 писал(а):Зачем переменные с именем "step***" имеют тип int, если принимают значения куда меньше 0xFF, т.е. идеально укладываются в байт?
точно, так и сделаю
mas123 писал(а):Вот просто попробуй себя в роли процессора: три раза подряд проверить: "а вдруг mig_count больше нуля"?

щас как раз пытаюсь соптимизировать этот кусок кода

я сначала быстро сделал общий вид, проверил на маленьких скоростях - работает. теперь оптимизация :shock:

вообще есть много переменных флагов - принимающих либо 1 либо ноль, но что-то не нашёл в описаниях переменных такого короткого типа переменной.(типа bit)
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
rxstart1
Вымогатель припоя
Сообщения: 508
Зарегистрирован: Пт фев 22, 2013 18:00:43
Откуда: Беларусь, г. Гомель

Re: как вывести младший байт в порт

Сообщение rxstart1 »

novarobotix писал(а):надо уменьшить время выполнения операции в программе. есть код:

PORTD.0=0;
PORTD.1=1;
PORTD.2=1;
PORTD.3=0;

можно ли эти 4 операции свести к одной? типа:
PORTDL=6;

то есть вывести одной командой первые 4 ноги порта а вторые 4 не трогать


Конечно есть способ обыкновенная маска по &
Аватара пользователя
novarobotix
Опытный кот
Сообщения: 759
Зарегистрирован: Пн май 12, 2014 06:13:33

Re: как вывести младший байт в порт

Сообщение novarobotix »

rxstart1 писал(а):Конечно есть способ обыкновенная маска по &

я пока непонимаю как это реализовать и насколько это будет быстрее чем сейчас сделано
пока код такой
Спойлер

Код: Выделить всё

#include <io.h>    // Хотим использовать порты ввода/вывода
#include <delay.h>  // Хотим использовать функции задержек
#include <math.h>
#include <string.h>
#include <stdlib.h>



int ob,corr_count,mig_count,correct;
unsigned int  n,k,n2,k2,nfp,nfp2,temp_mig_count;
unsigned char a[9];
unsigned char  temp2,temp_save2,temp,temp_save,i,temp_step,temp_step2,step=1,step2=1,dir,dir2,go_step,go_step2,c0,ob_temp,cd;

unsigned int n_prev;
//int p;

eeprom unsigned int n_eprom,n_eprom2,ob_eprom;


void mig(int v) {
                                       
for (i=0; i < v; i++)    {     //моргаем
PORTB.2=0; delay_us(100000);PORTB.2=1;delay_us(100000);PORTB.2=0;
   }
}



void main()

{
  DDRA=(0<<DDA7) | (0<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
  DDRB=(1<<DDB7) | (1<<DDB6) | (1<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);

a[1]=1;a[2]=3;a[3]=2;a[4]=6;a[5]=4;a[6]=12;a[7]=8;a[8]=9;

PORTA.0=1; // нормальное питание
nfp=n_eprom;
nfp=84; //вручную задаём момент включения кандёров
nfp2=n_eprom2;


while (1)
  {
  if (mig_count>0) temp_mig_count=temp_mig_count+1;
  if (temp_mig_count==2500) {PORTB.1=0;} //моргаем число пропусков
  if (temp_mig_count==5000) {PORTB.1=1;mig_count=mig_count-1;temp_mig_count=0;}

  if (PINB.3==1){ob_temp=0;}
  if (PINB.3==0 & ob_temp==0 & ob>100 & dir==1){
  if (c0==1){
  corr_count=ob-400;
  if (corr_count!=0) {correct=correct+corr_count;cd=0;mig_count=abs(correct);}  //PORTB.1=1;mig_count=mig_count+abs(abs(corr_count)/2);
             }
             ob_temp=1;
             ob=0;
             c0=1;
  } 
 
 
   if (k>100 || dir==2) cd=1;  // смотрим если менялось направление или была пауза чтобы скорректировать шаги
 
  if (PINB.0==1 & temp_save==0) {n_eprom=n;nfp=n;temp_save=1;mig(2);} // записываем в память значение включения конденсаторов
  if (PINB.0==0) {temp_save=0;}  // nfp - значение с которого включаются кандёры X
  n2=5;
  if (PINB.4==1 & temp_save2==0) {n_eprom2=n2;nfp2=n2;temp_save2=1;mig(2);} // записываем в память значение включения конденсаторов для Y
  if (PINB.4==0) {temp_save2=0;}   // nfp2 - для Y

 
 
   /////////////////////////////////////////////// канал Х ......................
  if (PINC.5==0) {dir=1;} //читаем направление
  if (PINC.5==1) {dir=2;}

  if (PINC.4==0) {temp_step=0;}  //читем шаг
  if (PINC.4==1 & temp_step==0) {
 

   if (nfp>k+2) {
   PORTD.0=0; //индицируем выключение кандёров
   PORTD.2=0; //выключаем кандёры
   }
 
  PORTB.2=0; //индицируем отключение простоя
  go_step=1;     // пойдём делать шаг 
  temp_step=1;
  n=k;k=0; // обнуляем счётчик и узнаём время между импульсами n
 
  if (correct>=0 || cd==0) {  // шаг в одну сторону если нет коррекции
  if (step==8 & dir==1) {step=1;temp=1;ob=ob+1;};
  if (step<8 & dir==1 & temp==0) {
  step++;temp=1;ob=ob+1;
 }
 }
 if(dir==1 & correct<0 & cd==1) correct++;
 
  if (correct<=0)     { // шаг в другую сторону если нет коррекции
  if (step>1 & dir==2 & temp==0) {
  step--;temp=1;ob=ob-1;
  }
  if (step==1 & dir==2 & temp==0) {step=8;temp=1;ob=ob-1;}
  }
                   
 if(dir==2 & correct>0) correct--;
 
  temp=0;
  if (ob==-400) ob=0; 
  PORTC=a[step]; //выводим на мотор   
  }
 
   
if (  nfp<n-2 ) {
   PORTD.0=1;  //индицируем включение кандёров
   PORTD.2=1; //включаем кандёры
 }
 
  if (k>5000)   //режим простоя
  {   
  PORTB.2=1; //индицируем  режим простоя
  PORTC=0; //отключаем обмотки
  }
   
if (k<10000) k=k+1;
if (k2<10000) k2=k2+1; 
 
}
 
   
}
вообще прикольно работает, крутиш вал на несколько шагов рукой типа пропуски были, а программа возвращает на место. но глючит на высокой скорости.поэтому ловлю мух :solder:
Глупый не задает вопросы. Глупый и так все знает.
Ответить

Вернуться в «AVR»