Вектора прерываний от таймеров в MCS51 00bh 01bh 02bh соответственно. На этих адресах в памяти программ необходимо разположить подпрограмму ( процедуру ) обслуживания ( если очень коротенькая ) или JMP на таковую подпрограмму. На асм. это вообще очень просто - директивой ORG Например : ORG 0bh LJMP intT0 ;
intT0 : {команды процедуры....} ....... RETI ;
_________________ < виртуальная "кнопочка" >--( WWW ) <- Убедительная просьба интересующимся старыми компьютерами типа РК86 - не пишите в теме в барахолке, пишите Ваши вопросы в ( лс ) пожалуйста
Вопрос, про повторное использование кода. Имеется 51-й МК, к порту (скажем, P1) которого подключено 5 одинаковых датчиков, и надо организовать циклический опрос. Имеется подпрограмма, опрашивающая датчик, довольно сложная и громоздкая, в которой номер контакта с датчиком должен указан быть явно (например, P1.0). И давний, нерешенный для меня вопрос: чтоб не повторять текст этой подпрограммы 5 раз (надо много места), как передать ей номер контакта, который она опросит. Косвенной адресацией, с инкрементом регистра-указателя - никак, указатель указывает на оперативную память, а не на биты защелки порта. Вопрос решаем аппаратно, с использованием микросхемы коммутатора, типа какой нибудь КП, но хотелось чисто программно. Язык- ассемблер.
Номер линии указывается "скользящей" маской размещенной в отдельном буфер-регистре. Обработку проводим также не напрямую с линиями порта, а с защелкнутыми в буфер данными с целевого порта. Это если позволяет быстродействие. Оптимум - двунаправленный коммутатор.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Комрады! что за чудо КМ1816ВЕ51. в лабазах есть либо КР... либо вообще без букв в начале и с ромбиком, но по скотской цене.
СпойлерДали задачку(курсовик) решить на этом вымершем чуде. Препод возрастом с эти кристаллы, то что наши кое как научились клепать клоны AVR, и лицензировались в ARM...и писать на АСМе уже не есть "хороший тон" - воспринимать не хочет... ну да и пущай подавицц0... мне не жалько соответствено возникло пару вопросов: 0. Отличие КМ от КР и "без буквы" с точки зрения комманд. 1. чем компилировать/в чем писать? 2. чем и как шьется это чудо, если я таки да! соберу прототипЪ. 3. иностранные аналоги?/Модели в Proteus ?
Комрады! что за чудо КМ1816ВЕ51. в лабазах есть либо КР... либо вообще без букв в начале и с ромбиком, но по скотской цене.
СпойлерДали задачку(курсовик) решить на этом вымершем чуде. Препод возрастом с эти кристаллы, то что наши кое как научились клепать клоны AVR, и лицензировались в ARM...и писать на АСМе уже не есть "хороший тон" - воспринимать не хочет... ну да и пущай подавицц0... мне не жалько соответствено возникло пару вопросов: 0. Отличие КМ от КР и "без буквы" с точки зрения комманд. 1. чем компилировать/в чем писать? 2. чем и как шьется это чудо, если я таки да! соберу прототипЪ. 3. иностранные аналоги?/Модели в Proteus ?
Заранее спасибо за ответы
КМ1816ВЕ51 работает только с внешним ПЗУ (27С256/27С512) плюс дополнительный регистр. Максимальная частота 12МГц (стандартно предпочтение более низкой в связи с довольно обширной "монтажной паутиной"). Полная схемка (с избытком) здесь: viewtopic.php?p=3006535#p3006535 В результате имеем аналог АТ89С2051 с определяемым ПЗУ объёмом памяти программ и порты Р1 и Р3 с ограничением по выходной нагрузочной способности с приличным потреблением питания. В принципе съедобно. Для написания прожек или ассемблер (полномасштабный фриваре у атмела, есть превосходная IDE также фриваре, но ассемблер с несколько отличающимся синтаксисом и "урезанный" (ознакомительный) варьянт IDE от кейл). В ознакомительном варианте исходники на ассемблере и схемки проектов где-то тут раскиданы: viewtopic.php?f=62&t=94201&start=200 Ну и насчет "...писать на АСМе уже не есть "хороший тон"..." - на ассемблере надо иметь соответствующие знания по составлению исходников - просто о серъёзном подходе уже даавно позабыли (даже нужную информацию нарыть порой нереально).
0. Отличие КМ от КР и "без буквы" с точки зрения комманд. 1. чем компилировать/в чем писать? 2. чем и как шьется это чудо, если я таки да! соберу прототипЪ. 3. иностранные аналоги?/Модели в Proteus ?
0.Никаких особых отличий. Заморочки с типом корпуса. С ромбиком - военная приемка типа, оттуда скотская цена. 1. Смотря какой язык выбрать. Если на ассемблере, то могу посоветовать, MCU 8051 IDE. Там ассемблер, среда разработки и эмулятор. 2. Шьется не это чудо, шьется программатором микросхема ПЗУ внешнего блока памяти программ. Если взять Winbond W27C512, то можно шить относительно доступным программатором TL866 3. Intel P8051 (почти точный аналог). МК на основе MCS-51 очень много, и большинство из них более удобны чем эта, хотя-бы засчет наличия флэш-памяти. Модели в протеусе нет (есть, нерабочая), но можно выбрать там, например AT89C51, что в общем тоже самое.
Мне тут авторитетно посоветовали одну книжечку..."Проектирование цифровых устройств на однокристальных микроконтроллерах Автор: Сташин В.В. 1990". Нашел ))) сундук весч полезная))) Там на 10 странице, в таблице 1.1. для моего случая "ве51" - указано, что емкость резидентной памяти программ - 4 килограмма. До этого плотно писал авр8, немного потыкал в стм32...вобщем я понимаю, что это и есть пзу для прошивки? Ну или бутлоадера...? Ибо 4 килограмма - мало(((
У 1816ВЕ51 РПД и в помине не имелось. А по системе команд - объема в 2К "за глаза" хватить (жаже если тупо сравнивать с АВРками - 2К у 51-й = 4К у АВР). Бутлоадер сам пиши (или ищи китаяцкие варианты).
в советких АОН ползовали любые 40или 44ногие 51-52мк с внешней памятью через 373 374 регистры 27512 27010 что скажете насчетэтого конфига для переделки под чтото полезное кстати обнаружил страную 8ногую память там A51SC c350 чоб это такое значило? внешней рамы там нет плата s0ul 116-4 прошивка telur какоенинить пррименени возможно полезное ?
_________________ ZМудрость(Опыт и выдержка) приходит с годами. Все Ваши беды и проблемы, от недостатка знаний. Умный и у дурака научится, а дураку и .. Алберт Ейнштейн не поможет и ВВП не спасет.и МЧС опаздает
sbit FRSTDAT=P7^6; //indicate when the Read Channel 1(V1)data=1; sbit HBEN=P4^3; //DB14,select output: 1=output high 8 bits, after the output of the low 8-bit sbit BUSY=P7^7; //at high level to read data
sbit AD_DoutA=P2^0; //DB7,Serial mode is used,the output data Dout A sbit AD_DoutB=P4^4; //DB8,Serial mode is used,the output data Dout B
/* ***************************************************************************** * Function name: ad7606_Reset * Function Description: hardware reset, the AD7606 * Arguments: none * Return value: none ***************************************************************************** */ void ad7606_Reset(void) { /* The AD7606 is a high-level reset bit, the requirements of the minimum pulse width 50ns */
ADC_RST=0;
ADC_RST=1; ADC_RST=1; ADC_RST=1; ADC_RST=1; Delay1ms(); ADC_RST=0; } /* ********************************************************************************************************* * Function name: ad7606_StartConv * Function Description: start the AD7606 ADC conversion * Arguments: none * Return value: none ********************************************************************************************************* */ void ad7606_StartConv(void) { /* Rising edge starts the conversion, the low level duration of at least 25ns */ CONVST=0; CONVST=0; CONVST=0; /* continuous implementation of the 2 times, a low level of about 50ns */ Delay10us(); CONVST=1; Delay100us(); Delay100us(); // Delay100us(); } //******************************************************************************// void AD7606_init() { Delay1ms();
ad7606_Reset(); OS2=1;OS1=1;OS0=0; //set oversampling ADC_CS1=1; ADC_CS2=1; P2=0x80; RD_SCK=1; CONVST=1; RANGE=0; //select+/- 5V input HBEN=0; //DB14,select output: 1=output high 8 bits, after the output of the low 8-bit }
// TODO: figure out what these actually do // UMPL source code is not very obivous #define MPU6050_DMPINT_5_BIT 5 #define MPU6050_DMPINT_4_BIT 4 #define MPU6050_DMPINT_3_BIT 3 #define MPU6050_DMPINT_2_BIT 2 #define MPU6050_DMPINT_1_BIT 1 #define MPU6050_DMPINT_0_BIT 0
int main(void) { u8 Re = 0, Read = 0,TempBuf1,TempBuf2,TempBuf3; short temp1[3]; short temp2[3]; short temp3; u8 Temp1Buf1,Temp1Buf2,Temp1Buf3; u8 Temp2Buf;
The present program tests the use of STC15W401AS-35I-SOP16<RMB1. 6>to drive the model aircraft with Sensorless brushless three-phase DC motor.
The program reference from the online code(author: Swiss life), modified to.
Circuit diagram, see the file "BLDC-V10-experimental circuit. the pdf".
The control signal from the P3. 2-input positive pulse signal, at intervals of 5~20ms, pulse width of 1. 000~1.610 ms.
1.160 ms started, 1.610 ms for the highest speed, with a resolution of 2us.
This app is just simple to control, the software is not treated 0 delay 30 degrees switching overcurrent detection.
Due to the 0 detection portion has a RC filter, so changing the capacitance value may be approximately corresponding to the highest speed when the delay of 30 degrees time.
Interested persons can self-improvement circuit and program.
******************************************/
#define MAIN_Fosc 24000000L //define the main Clock
#include "STC15Fxxxx. H"
#define MCU_PIN 16 /* select MCU pin count, supports only 16 or 20 feet(28 feet or 32 of the heel 20 of the foot the same) */
//CMPCR1 #define CMPEN 0x80 //1: allow the comparator, 0: disable,turn off comparator power supply #define CMPIF 0x40 //comparator interrupt flag, including the rising edge or the falling edge of the interrupt, software clears to 0 #define PIE 0x20 //1: comparison of results from 0 to 1, generating a rising edge interrupt #define NIE 0x10 //1: result of the comparison by the 1 becomes 0, generates a falling edge interrupt #define PIS 0x08 //input of positive polarity is selected, 0: choose an external P5. 5 do n-input, 1: by ADCIS[2:0]select the ADC input end to do the positive input. #define NIS 0x04 //input negative polarity select, 0: select internal BandGap voltage BGv do negative input, 1: Select the external P5. 4 do input. #define CMPOE 0x02 //1: allow the comparison result is output to P1. 2, 0: disable. #define CMPRES 0x01 //the comparison result, a 1: CMP+level is higher than the CMP-, 0: CMP+level is lower than the CMP-is, read-only
//CMPCR2 #define INVCMPO 0x80 //1: comparator output inverted, 0: No invert #define DISFLT 0x40 //1: closed 0. 1uF filtering, 0: allows #define LCDTY 0x00 //0 to 63, the comparison result changes in the delay period
void StepXL(void) // change the phase sequence function { switch(Step) { case 0: // AB PWM0_L=0; PWM2_L=0; CCAP0H = PWM_Value; CCAP1H=0; CCAP2H=0; // open A phase of the high-end PWM1_L = 1; // Turn on phase B low-side ADC_CONTR = 0XED; // choose P1. 5 as ADC input i.e. the phase c voltage CMPCR1 = 0x9C; //bit7=1 enables the comparator, bit4=1 comparison of results from 1 becomes 0, generates a falling edge interrupt (not in response to the falling edge of the interrupt?) break; case 1: // AC PWM0_L=0; PWM1_L=0; CCAP0H = PWM_Value; CCAP1H=0; CCAP2H=0; // open A phase of the high-end PWM2_L = 1; // Turn on phase C low-side ADC_CONTR = 0XEC; // choose P1. 4 as ADC input i.e. the phase B voltage CMPCR1 = 0xAC; //rising edge interrupt
break; case 2: // BC PWM0_L=0; PWM1_L=0; CCAP0H=0; CCAP2H=0; CCAP1H = PWM_Value; // open the B phase of the high-end PWM2_L = 1; // Turn on phase C low-side ADC_CONTR = 0XEB; // choose P1. 3 as an ADC input, i.e. the a-phase voltage CMPCR1 = 0x9C; //falling edge interrupt break; case 3: // BA PWM1_L=0; PWM2_L=0; CCAP0H=0; CCAP2H=0; CCAP1H = PWM_Value; // open the B phase of the high-end PWM0_L = 1; // Open A phase of the low-end ADC_CONTR = 0XED; // choose P1. 5 as ADC input i.e. the phase c voltage CMPCR1 = 0xAC; //rising edge interrupt
break; case 4: // CA PWM1_L=0; PWM2_L=0; CCAP0H=0; CCAP1H=0; CCAP2H = PWM_Value; // open the C phase of the high-end PWM0_L = 1; // Open A phase of the low-end ADC_CONTR = 0XEC; // choose P1. 4 as ADC input i.e. the phase B voltage CMPCR1 = 0x9C; //falling edge interrupt break; case 5: // CB PWM0_L=0; PWM2_L=0; CCAP0H=0; CCAP1H=0; CCAP2H = PWM_Value;// open the C phase of the high-end PWM1_L = 1; // Turn on phase B low-side ADC_CONTR = 0XEB; // choose P1. 3 as an ADC input, i.e. the a-phase voltage CMPCR1 = 0xAC; //rising edge interrupt
// CMOD = 1 << 1; //Select system clock/2 as the clock source, i.e. PWM frequency=24M/2/256=46.9 K CMOD = 5 << 1; //Select system clock/4 Clock source, i.e. PWM frequency=24M/4/256=23.4 K // CMOD = 6 << 1; //Select system clock/6 Clock source, i.e. PWM frequency=24M/6/256=15.6 K CL=0; // PCA counter is cleared CH=0;
PCA_PWM0 = 0X00; CCAP0H=0; // initialize duty cycle is 0% the value of H is loaded into the L CCAP0L=0; CCAPM0=0x42; // set to PWM mode
PCA_PWM1 = 0X00; CCAP1H=0; // initialize duty cycle to 0% CCAP1L=0; CCAPM1=0x42; // set to PWM mode
PCA_PWM2 = 0X00; CCAP2H=0; // initialize duty cycle to 0% CCAP2L=0; CCAPM2=0x42; // set to PWM mode
CR = 1; }
void ADC_Init(void) { P1n_pure_input(0x38); P1ASF = 0X38; // turn P1. 3 P1. 4 P1. 5 AD input port }
void CMP_INT(void) interrupt 21 { CMPCR1 &= ~0X40; // need the software to clear the interrupt flag if(Step<5) Step++; else Step = 0; StepXL(); TimeOut = 10; //10ms timeout }
void CMP_Init(void) { CMPCR1 = 0X8C; // 1000 1100 open the comparator P5. 4 as a comparator the inverting input terminal of the ADC pin as the positive input end of the CMPCR2 = 60; // 60 Clock filter P5n_pure_input(0x10); }
void T0_Iint(void) { Timer0_AsTimer(); /* timer 0 is used as timer */ Timer0_12T(); /* Timer0 clodk = fo/12 12 divider, default */ Timer0_16bit(); Timer0_Gate_INT0_P32(); /* timer 0 by the external INT0 high level allows the timer to count */ TH0 = 0; TL0 = 0; TR0 = 1; // Turn on timer 0 ET0 = 1;// allow ET0 interrupt }
void T0_Interrupt(void) interrupt 1 { Rx_cnt = 0; //once the overflow occurs, the start of the n pulses is invalid RxPulseWide = 1000; //stop B_RxOk = 1; //virtual receive a pulse }
if(B_RxOk) //receive a pulse { B_RxOk = 0; j = RxPulseWide; if(j >= 1100) // 1100~1610 corresponding to the PWM duty ratio of 0~255 { j = (j - 1100) >> 1; //2us corresponding to the PWM for a stepper if(j > 256) j = 255; } else j = 0; PWW_Set = (u8)j; }
if(! B_RUN && (PWW_Set >= 30)) // PWM_Set >= 30, and the motor is not running, then start the motor { StartMotor(); // start the motor CMPCR1 &= ~0X40; // need the software to clear the interrupt flag ENABLE_CMP_INT; // turn comparator interrupt B_RUN = 1; TimeOut = 0; }
void time_init() //timer initialization { TMOD=0x11; //set the timer T0,T1 is a working way to 1. TH0=(65536-25000)/256; //timer 0 high 8-bit initial loading value of the timing 50ms) TL0=(65536-25000)%256; //timer 0 lower 8 bits of the initial fill value of the timing 50ms) EA=1; //Open General interrupt. ET0=1; //Open timer 0 interrupt TR0=1; //Start the timer to 0. }
void AD_init() //AD initialization { P1M0=0xff; P1M1=0xff; //set P1 port minimum 4-bit open-drain mode, used for AD collection. ADC_CONTR=0xe0; //1110 0000 turn on AD Converter power supply, set the conversion speed is 210 clock cycles conversion 1 times. delayms(10); }
uint GetAD(uchar channel) //the AD conversion, the channel to convert the channel number 0~7. { uchar AD_finished=0; uint result; //define an int type variable, to save the AD converted data. ADC_CONTR|=channel; //select AD conversion channel number. ADC_DATA=0; ADC_LOW2=0; ADC_CONTR|=0x08; //start the AD conversion. while(AD_finished==0) //wait for the AD conversion ends. { AD_finished=(ADC_CONTR&0x10); //query ADC_FLAG bit is set to 1; } result=ADC_DATA*4+ADC_LOW2; ADC_CONTR&=0xe0; //turn off AD Converter return(result); //conversion completed return value. }
float Ad_Av(uchar channel) //continuous AD acquisition N times, and then averaged. { float Val_Av=0; //define one used to save the real voltage value of float type variables. uchar num; //define one used to capture the loop variable. for(num=100;num>0;num--) { Val_Av+=GetAD(channel); //for N times acquisition summation. } Val_Av=Val_Av/100; //for N times collection averaged return(Val_Av); //put Val_Av the value of the return. }
void lcd_init() //LCD initialization { lcdrw=0; lcden=0; write_com(0x38); //write instruction, set the 1602 is a 16X2 display, 5x7 dot matrix, 8-bit data interface. write_com(0x0c); //write instruction, set the opening display does not display the cursor. write_com(0x06); //write 1 byte after the address pointer is automatically incremented by 1. write_com(0x01); //display cleared to 0, the data pointer is cleared to 0. write_com(0x80); //positioning of the 1602 data pointer to 0X08 }
void write_lcd1(uint ad1) //the I circuit voltage AD sampling split after 1602 display { write_com(0x80); if(ad1/1000>=1) //Voltage if less than 10V, the 1-bit display is empty. { write_data(0x30+ad1/1000); } else write_data(' '); write_data(0x30+ad1%1000/100); write_data('.'); write_data(0x30+ad1%100/10); write_data(0x30+ad1%10); write_data('V'); }
void write_lcd2(uint ad2) //the I-channel current AD sample split after 1602 display { write_com(0x88); write_data(0x30+ad2/1000); write_data('.'); write_data(0x30+ad2%1000/100); write_data(0x30+ad2%100/10); write_data(0x30+ad2%10); write_data('A'); }
void main() { float ad0,ad1,ad2; AD_init(); //AD initialization lcd_init(); //LCD initialization. time_init(); //timer initialization. while(1) { if(num==20) //num=20, indicating that 1 second the time is up, is performed once the AD sampling and LCD display refresh. { num=0; //the num is cleared to 0 for the next count. TR0=0; //turn off timer 0 ad0=Ad_Av(0); //0-channel AD sampling(0 channel as a reference voltage in. ad1=Ad_Av(1); //1 channel AD sampling I-channel voltage sampling it. ad2=Ad_Av(2); //2-channel AD sampling I circuit current sampling in.
ad1=ad1*2480/ad0; //calculate the 1-channel actual Voltage, the actual voltage= actual sampling value*reference voltage mv/reference sample value ad2=ad2*2480/ad0; //calculate the 2-channel actual Voltage, the result is assigned to ad2. write_lcd1(ad1); write_lcd1(ad1*0.6); //put the ad1 value is sent to the LCD display. Calculate the voltage that is sent to the AD voltage is attenuated by 6 times. write_lcd2(ad2); //put the ad2 value is sent to the LCD display. Calculate the current. Current sampling resistor is 0. 1 Europe, in an enlarged 10 times TR0=1; //Start the timer to 0. } } }
народ что скажете про http://www.dragonchip.com/TechDoc/Selec ... 130301.pdf презентовали парочку сэмплов DC6688F30SB хотелось бы вкосячить в корпус любого пулта и подружить с этой шаской Шасси HOXI M9E19C V1.2 ?(маркировка платы) Проц. Под радиатором -приклееным Flash F25L004A Eeprom 24c32 звTDA7266SA
Добавлено after 5 minutes 11 seconds: проблема телек год без пулта! подобрать нереално -ну не тащить же в магазин перепробоваи с полсотни уже (я и другие =мне уже не дают с пробой)сейчас юзается толко через прововский бокс с кабелным
Добавлено after 5 minutes 44 seconds: я правилно понял что он imtncz по SPI тоесть в прогере под 25*ххх должен видется как флеха на 30к? или он тока на Кейл write не пинать! я 1раз вижу такие
_________________ ZМудрость(Опыт и выдержка) приходит с годами. Все Ваши беды и проблемы, от недостатка знаний. Умный и у дурака научится, а дураку и .. Алберт Ейнштейн не поможет и ВВП не спасет.и МЧС опаздает
Доброго времени суток. Как в асме MCS-51 объявить макрос глобальным ? Метку (подпрограмму) вроде как разобрался, а вот макрос никак не могу. Понимаю что для разных IDE может быть по разному, но вот когда разбирался с метками, нашел пример для Кейла, сделал как было написано, моя IDE (MCStudio) матюкнулась на неправильные параметры, я переделал по ее подсказкам и все вроде получилось. Думаю что и с макросом так может прокатить, так что подскажите как знаете (сам принцип), а я уже постараюсь разобраться.
П.С. Как обычно, спросишь что-то, потом засядешь поглубже и сам разберешься. Короче засунул макрос в файл Macro.inc и директивой include 'Macro.inc' подключил во всех требуемых файлах проекта, до директивы объявления сегмента перемещаемого кода:
Код:
include 'Macro.inc' <НАЗВАНИЕ СЕГМЕНТА> segment code rseg <НАЗВАНИЕ СЕГМЕНТА>
Не знаю, насколько это "расово правильно", но работает
Доброго времени суток. В журнале "Радиолюбитель" №3,2008г. уважаемый ARV опубликовал статью из цикла "МК для начинающих" в которой был показан оригинальный способ вывода строк, как на языке высокого уровня. Я стал частенько использовать описанный способ, потому что он действительно иногда очень удобен (бывает, что строки удобнее видеть прямо в конкретном месте алгоритма, а не собранные в кучу где-то в конце исходника). Не так давно я озадачился разбором (парсингом) строк. Я решил нагло передрать вышеуказанный способ и использовать его для своих целей. Вот что в итоге получилось: Спойлер
Код:
; Тип: функция, вызываемая в макросе ; Передаваемые параметры: String,Label,Waiting_value ; Возвращаемое значение: jmp на Label в случае ошибки парсинга String
Parsing macro String,Label,waiting_value ; строка для сравнения, метка для перехода в случае ошибки, время ожидания каждого символа строки в Х*256 мкс mov parsing_delay,waiting_value call Intput db String,0Dh,0Ah,0 jbc parsing_error,Label ; Проверяем признак ошибки парсинга endm
public Intput public parsing_delay,parsing_error
USE_DATA_SEG equ 1 ; Использовать автовыделение памяти под сегменты данных USE_BIT_SEG equ 1 ; Использовать автовыделение памяти под сегменты битовых данных
if USE_DATA_SEG Parsing_data segment data rseg Parsing_data parsing_delay: ds 2 else parsing_delay equ 1Eh ; Распределяем память вручную. Учитываем, что надо 2 ячейки: parsing_delay и parsing_delay+1 endif
if USE_BIT_SEG Parsing_bit segment bit rseg Parsing_bit parsing_error: dbit 1 else parsing_error bit 20h.0 ; Распределяем биты вручную endif
Parsing_code segment code rseg Parsing_code
Intput: ; Описываем процедуру, вызываемую из макроса pop DPH ; Извлекаем из стека в DPTR адрес возврата, pop DPL ; там находиться адрес 1 символа строки Loop_Intput: clr A movc A, @A+DPTR ; Получаем очередной символ из строки inc DPTR ; Сразу берем следующий символ jnz Wait ; Если не конец строки, проверяем jmp @A+DPTR ; А теперь маленький грязный хак. В DPTR у нас адрес команды после строки, вернемся по этому адресу Wait: ; Принимаем и сравниваем полученный символ с символом из строки if USE_DATA_SEG mov parsing_delay+1,#0 else clr parsing_delay+1 endif push ACC mov A, parsing_delay jz Always_Wait ; Если задержка ожидания = 0 Loop_Wait: jb RI, Stop_Wait ; Если принят байт, прекращаем ожидание djnz parsing_delay+1,Loop_Wait djnz parsing_delay,Loop_Wait ; Цикл ожидания входящего байта jmp Exit_Intput ; Время ожидания байта истекло, на выход с восстановлением АСС Always_Wait: jnb RI, $ ; Ждем байт неограниченно долго Stop_Wait: pop ACC mov parsing_delay,SBUF ; Используем ячейку задержки для сравнения полученого символа с символом из строки clr RI cjne A,parsing_delay,Exit_Intput_2; Если хоть 1 полученный символ не совпал, на выход без восстановления АСС jmp Loop_Intput ; Иначе повторяем цикл сравнения Exit_Intput: ; Выход по превышению времени парсинга pop ACC Exit_Intput_2: ; Выход по ошибке парсинга clr A movc A, @A+DPTR inc DPTR jnz Exit_Intput_2 ; Ищем конец строки setb parsing_error ; Устанавливаем признак ошибки парсинга jmp @A+DPTR ; А теперь маленький грязный хак. В DPTR у нас адрес команды после строки, вернемся по этому адресу
Теперь парсинг строки выглядит легко и непринужденно: Спойлер
Код:
Parsing 'Hello',Error_1,0
clr P2.0 ; действие в случае успеха jmp $
Error_1:
clr P2.7 ; действие в случае провала jmp $
Существенный минус этого подхода при парсинге это то, что прием байта все-таки лучше делать в прерывании. П.С. Хотя вот реализовал и в прерывании, получилось даже чуть проще, но теряется преимущество прерывания - асинхронность. Надо делать кольцевой буфер, писать байты в него, по приему нужного количества начинать парсинг, все верно ?
Добрый день. Не подскажите, как для MCS-51 можно реализовать 16-битный последовательный сдвиг с использованием только битовых операций - CPL, CLR, SETB, JB, JNB. ANL, ORL использованием бит-адресуемых ячеек ОЗУ. 16-битный двоичный счетчик смог реализовать таким образом, на сдвиговый регистр ума не хватает.
Сейчас этот форум просматривают: Sergeaudi и гости: 23
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения