Вектора прерываний от таймеров в MCS51 00bh 01bh 02bh соответственно.
На этих адресах в памяти программ необходимо разположить подпрограмму ( процедуру ) обслуживания ( если очень коротенькая ) или JMP на таковую подпрограмму.
На асм. это вообще очень просто - директивой ORG
Например :
ORG 0bh
LJMP intT0 ;
intT0 : {команды процедуры....} .......
RETI ;
< виртуальная "кнопочка" >--( WWW ) <- Убедительная просьба интересующимся старыми компьютерами типа РК86 - не пишите в теме в барахолке, пишите Ваши вопросы в ( лс ) пожалуйста
Вопрос, про повторное использование кода. Имеется 51-й МК, к порту (скажем, P1) которого подключено 5 одинаковых датчиков, и надо организовать циклический опрос. Имеется подпрограмма, опрашивающая датчик, довольно сложная и громоздкая, в которой номер контакта с датчиком должен указан быть явно (например, P1.0). И давний, нерешенный для меня вопрос: чтоб не повторять текст этой подпрограммы 5 раз (надо много места), как передать ей номер контакта, который она опросит. Косвенной адресацией, с инкрементом регистра-указателя - никак, указатель указывает на оперативную память, а не на биты защелки порта.
Вопрос решаем аппаратно, с использованием микросхемы коммутатора, типа какой нибудь КП, но хотелось чисто программно.
Язык- ассемблер.
Номер линии указывается "скользящей" маской размещенной в отдельном буфер-регистре.
Обработку проводим также не напрямую с линиями порта, а с защелкнутыми в буфер данными с целевого порта. Это если позволяет быстродействие.
Оптимум - двунаправленный коммутатор.
Комрады! что за чудо КМ1816ВЕ51.
в лабазах есть либо КР... либо вообще без букв в начале и с ромбиком, но по скотской цене. СпойлерДали задачку(курсовик) решить на этом вымершем чуде. Препод возрастом с эти кристаллы, то что наши кое как научились клепать клоны AVR, и лицензировались в ARM...и писать на АСМе уже не есть "хороший тон" - воспринимать не хочет... ну да и пущай подавицц0... мне не жалько
соответствено возникло пару вопросов:
0. Отличие КМ от КР и "без буквы" с точки зрения комманд.
1. чем компилировать/в чем писать?
2. чем и как шьется это чудо, если я таки да! соберу прототипЪ.
3. иностранные аналоги?/Модели в Proteus ?
c2n писал(а):Комрады! что за чудо КМ1816ВЕ51.
в лабазах есть либо КР... либо вообще без букв в начале и с ромбиком, но по скотской цене. СпойлерДали задачку(курсовик) решить на этом вымершем чуде. Препод возрастом с эти кристаллы, то что наши кое как научились клепать клоны AVR, и лицензировались в ARM...и писать на АСМе уже не есть "хороший тон" - воспринимать не хочет... ну да и пущай подавицц0... мне не жалько
соответствено возникло пару вопросов:
0. Отличие КМ от КР и "без буквы" с точки зрения комманд.
1. чем компилировать/в чем писать?
2. чем и как шьется это чудо, если я таки да! соберу прототипЪ.
3. иностранные аналоги?/Модели в Proteus ?
Заранее спасибо за ответы
КМ1816ВЕ51 работает только с внешним ПЗУ (27С256/27С512) плюс дополнительный регистр.
Максимальная частота 12МГц (стандартно предпочтение более низкой в связи с довольно обширной "монтажной паутиной").
Полная схемка (с избытком) здесь: http://radiokot.ru/forum/viewtopic.php? ... 5#p3006535
В результате имеем аналог АТ89С2051 с определяемым ПЗУ объёмом памяти программ и порты Р1 и Р3 с ограничением по выходной нагрузочной способности с приличным потреблением питания.
В принципе съедобно.
Для написания прожек или ассемблер (полномасштабный фриваре у атмела, есть превосходная IDE также фриваре, но ассемблер с несколько отличающимся синтаксисом и "урезанный" (ознакомительный) варьянт IDE от кейл).
В ознакомительном варианте исходники на ассемблере и схемки проектов где-то тут раскиданы: http://radiokot.ru/forum/viewtopic.php? ... &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Мудрость(Опыт и выдержка) приходит с годами.
Все Ваши беды и проблемы, от недостатка знаний.
Умный и у дурака научится, а дураку и ..
Алберт Ейнштейн не поможет и ВВП не спасет.и МЧС опаздает
/************* Function Description**************
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
#if (MCU_PIN == 20)
sbit PWM2_L = P3^4;
sbit PWM1_L = P3^5;
sbit PWM0_L = P3^6;
#endif
#if (MCU_PIN == 16)
sbit PWM2_L = P5^5;
sbit PWM1_L = P3^3;
sbit PWM0_L = P3^6;
#endif
u8 Step;
u8 PWM_Value; // determine the PWM duty cycle value
u16 RxPulseWide;
bit B_RxOk;
bit B_RUN;
u8 PWW_Set;
u8 cnt10ms;
u8 Rx_cnt;
u8 TimeOut; //block timeout
#define DISABLE_CMP_INT CMPCR1 &= ~0X40 // turn off comparator interrupt
#define ENABLE_CMP_INT CMPCR1 |= 0X40 // turn comparator interrupt
/*************************/
void Delay_n_ms(u8 dly)
{
u16 j;
do
{
j = MAIN_Fosc / 13000; //delay 1ms, the main program in this beats running under
while(--j) ;
}while(--dly);
}
void delay_us(u8 us)
{
do
{
NOP(20); //@24MHz
}
while(--us);
}
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
break;
default:
break;
}
}
void PWM_Init(void)
{
PWM0_L = 0;
PWM1_L = 0;
PWM2_L = 0;
#if (MCU_PIN == 20)
P3n_push_pull(0x70);
#endif
#if (MCU_PIN == 16)
P3n_push_pull(0x48);
P5n_push_pull(0x20);
#endif
// 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);
}
u8 StartMotor(void)
{
u16 timer,i;
DISABLE_CMP_INT; // disable comparator interrupt
PWM_Value = 30; // initial duty ratio=16/256=6%
Step = 0;
StepXL(); // initial position
Delay_n_ms(5);//delay_ms(5);
timer = 300;
while(1)
{
for(i=0; i<timer; i++) delay_us(50); //
timer -= timer /15 + 1;
if(timer < 25) return(1);
if( Step < 5) Step++;
else Step = 0;
StepXL();
}
}
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
}
/********************* INT0 interrupt function*************************/
void INT0_int (void) interrupt INT0_VECTOR
{
u16 j;
TR0 = 0;
j = ((u16)TH0 << 8) + TL0;
TH0 = 0;
TL0 = 0;
TR0 = 1;
if(++Rx_cnt >= 5) Rx_cnt = 5;
j >>= 1; //In order to handle, turn into units of us
if((j >= 800) && (j <= 2000) && (Rx_cnt == 5))
{
RxPulseWide = j;
B_RxOk = 1; //flag receive a pulse
}
}
/**********************************************/
void main(void)
{
u16 j;
PWM_Init();
ADC_Init();
CMP_Init();
T0_Iint();
IE0 = 0; // clear external interrupt 0 flag
EX0 = 1; // INT0 Enable
IT0 = 1; //INT0 falling edge interrupt
RxPulseWide = 1000;
PWW_Set = 0;
cnt10ms = 0;
Rx_cnt = 0;
TimeOut = 0;
EA = 1; // Turn on total interrupt
while (1)
{
Delay_n_ms(1); //delay 1ms, the main program in this beats running under
if(TimeOut > 0)
{
if(--TimeOut == 0) //stall timeout
{
CCAP0H=0; CCAP1H=0; CCAP2H=0; // duty cycle is 0
PWM0_L=0; PWM1_L=0; PWM2_L=0;
DISABLE_CMP_INT; // off comparator interrupt
Delay_n_ms(250); //stall,delay 1 sec then start
Delay_n_ms(250);
Delay_n_ms(250);
Delay_n_ms(250);
RxPulseWide = 1000;
PWW_Set = 0;
PWM_Value = 0;
B_RxOk = 0;
B_RUN = 0;
Rx_cnt = 0;
TimeOut = 0;
}
}
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;
}
if(++cnt10ms >= 10) // 10ms time slot
{
cnt10ms = 0;
if(B_RUN)
{
if(PWM_Value < PWW_Set) PWM_Value++;
if(PWM_Value > PWW_Set) PWM_Value--;
if(PWM_Value < 20) // stopped
{
PWM_Value = 0;
B_RUN = 0;
CCAP0H=0; CCAP1H=0; CCAP2H=0; // duty cycle is 0
PWM0_L=0; PWM1_L=0; PWM2_L=0;
DISABLE_CMP_INT; // off comparator interrupt
}
}
}
}
}
#include<STC12C5410AD. h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P3^4; //LCD write command/data control terminal. RS=1 Data write; RS=0 writing instruction.
sbit lcdrw=P3^5; //LCD write control terminal; RW=0 write.
sbit lcden=P3^7; //LCD enable end.
uchar num;
void delayms(uint xms) //ms delay subroutine
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
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 T0_time() interrupt 1 //timer 0 interrupt sub-function.
{
TH0=(65536-25000)/256; //reload timer 0 high 8-bit value.
TL0=(65536-25000)%256; //reload timer 0 low 8-bit value.
num++;
}
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 write_com(uchar com) //1602 LCD write instruction.
{
lcdrs=0;
P2=com;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
void write_data(uchar date) //1602 LCD write data
{
lcdrs=1;
P2=date;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
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' подключил во всех требуемых файлах проекта, до директивы объявления сегмента перемещаемого кода:
Доброго времени суток. В журнале "Радиолюбитель" №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-битный двоичный счетчик смог реализовать таким образом, на сдвиговый регистр ума не хватает.