Код программы прилагаю
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Описание переменных
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
unsigned int pulses_a = 0; // истинное кол. импульсов
unsigned int pulses_b = 0; // истинное кол. импульсов
unsigned int oldstate1 = 1; // состояние кнопки 1
unsigned int oldstate2 = 1; // состояние кнопки 2
unsigned int oldstate3 = 1; // состояние кнопки 3
unsigned int menuitem = 1; // номер активного пункта меню
signed int count_z = 0; // частота импульсов Z канала
unsigned int f_limit = 1000000;// граничная допустимая частота входов
unsigned int z_max = 0; // maximal value of z pulses
unsigned int lim = 0; // лимит превышения срабатывания счетчика TRM0
char inter =0xB8;
signed int count = 0;
unsigned int pulses_def=1024; // предполагаемое количество импульсов энкодера
unsigned int error_a = 0; // ошибки энкодера А канала
unsigned int error_b = 0; // ошибки энкодера B канала
char txt[7]; // вывод на экран
unsigned int a_pulses = 0; // количество импульсов канала а
unsigned int b_pulses = 0; // количество импульсов канала в
unsigned int z_pulses = 0; // количество импульсов z-канала
unsigned int a_out = 0; // количество имп. на оборот
unsigned int b_out = 0; // количество имп. на оборот
unsigned short current_duty;
bit aold; // состояние канала А
bit bold; // состояние канала В
short zold = 0; // состояние канала Z
unsigned int m; // служебный бит
// присвоение сообщений
char device[7] = "DEVICE" ;
char ready[6] = "READY" ;
char pulses[7] = "PULSES" ;
char tys[7] = "+-1000" ;
char sot[6] = "+-100" ;
char dec[5] = "+-10" ;
char edi[4] = "+-1" ;
// конфигурирование портов дисплея
// Lcd pinout settings
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE2_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D4 at RC4_bit;
// Pin direction
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE2_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D4_Direction at TRISC4_bit;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Подпрограммы
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PWM1_Set_Duty(unsigned short duty_ratio);
void PWM1_Start(void);
void PWM1_Stop(void);
void InitMain(){
PWM1_Init(2000); // Initialize PWM1 module at 2 kHz
}
void interrupt(){
// обработка прерываний
INTCON.GIE = 0; // запрет прерываний
// прерывание по INT
if(INTCON.TMR0IF){ // при переполнение TMR0
INTCON.TMR0IF = 0; // сбрасываем флаг о его переполнение
count++;
}
if (INTCON.INTF == 1){
z_pulses++; // подсчёт по Z каналу
count_z++;
if(count<=lim){
count=0;
inter = 0xB0;
count_z=0;
zold=1;
}
else inter=0xB8;
count=0;
count_z=0;
}
if ((INTCON.INTF == 1)&&(z_pulses>1)){
if (a_pulses!=pulses_def)error_a++;
if (b_pulses!=pulses_def)error_b++;
pulses_a=a_pulses;
pulses_b=b_pulses;
a_pulses=0;
b_pulses=0;
z_pulses=1;
}
if (z_pulses==1){
if((PORTB.B5 > aold)&&(z_pulses > 0)) a_pulses++;
if((PORTB.B4 > bold)&&(z_pulses > 0)) b_pulses++;
if (PORTB.B5 != aold) aold = PORTB.B5;
if (PORTB.B4 != bold) bold = PORTB.B4;
}
m = PORTB;
INTCON = inter; // разрешение прерываний
}
void motor(){
// управление двигателем
Lcd_Cmd(_LCD_CLEAR);
InitMain();
current_duty = 100; // initial value for current_duty
//PWM1_Start(); // start PWM1
PWM1_Set_Duty(current_duty); // Set current duty for PWM1
INTCON = 0xB8;
while(1){ // endless loop
while(zold==1){
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, "tishe-tishe"); // Print text on LCD
zold=0;
delay_ms(200);
Lcd_Cmd(_LCD_CLEAR);
}
IntToStr(error_a, txt);
Lcd_Out(1, 1, txt);
Lcd_Out(1, 1, "A:"); // Print text on LCD
IntToStr(error_b, txt);
Lcd_Out(2, 1, txt); // Print text on LCD
Lcd_Out(2, 1, "B:"); // Print text on LCD
IntToStr(pulses_a, txt);
Lcd_Out(1, 8, txt);
IntToStr(pulses_b, txt);
//IntToStr(count, txt);
Lcd_Out(2, 8, txt);
delay_ms(500);
if(Button(&PORTA, 2, 10, 0)){
INTCON.GIE = 0;
break;
}
Lcd_Cmd(_LCD_CLEAR);
delay_ms(100);
while(Button(&PORTA, 0, 10, 0)){ // button on RA0 pressed
if(current_duty>=250)current_duty=255;
else current_duty=current_duty+10; // increment current_duty
PWM1_Set_Duty(current_duty);
IntToStr(current_duty, txt);
Lcd_Out(2, 1, txt);
Lcd_Out(1, 1, "speed "); // Print text on LCD
delay_ms(100);
}
while(Button(&PORTA, 1, 10, 0)){ // button on RA1 pressed
current_duty=current_duty-10; // decrement current_duty
if(current_duty<10)current_duty=10;
PWM1_Set_Duty(current_duty);
IntToStr(current_duty, txt);
Lcd_Out(2, 1, txt);
Lcd_Out(1, 1, "speed "); // Print text on LCD
delay_ms(100);
}
}
PWM1_Stop();
}
void program(){
// программа подсчёта импульсов
a_pulses = 0; // обнуление числа импульсов
b_pulses = 0; // обнуление числа импульсов
z_pulses = 0; // обнуление числа импульсов
z_max=f_limit/pulses_def; // макс. частота Z канала
lim = z_max/256;
motor(); // ВЫПОЛНЕНИЕ ПРОГРАММЫ ВРАЩЕНИЯ
menuitem = 1; // переход в начало меню
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// главная программа
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void main() {
//******************************************************************************
// Инициализация
//******************************************************************************
TRISA = 0xff; // PORTA
TRISB = 0b00110001; // PORTB входы каналы энкодера (0(INT),4,5) входы кнопок (1-3)
TRISC = 0x00; // PORTC выход данных LCD
TRISD = 0x00; // PORTD выхода управления двигателем (4-7)
TRISE = 0x00; // PORTE выход управления LCD
ADCON1 = 0x06; // входы - цифровые
PORTB = 0x00; // обнуление
PORTD = 0x00; // обнуление выходов
PORTC = 0x00; // обнуление выходов
PORTE = 0x00; // обнуление выходов
INTCON = 0x00; // запрет прерываний
OPTION_REG = 0b10000001; // прерывания INT по спаду
//assing prescaler to the TMR0, with 1:256 rate
PIE1 = 0x00; //
PIR1 = 0x00; //
PIE2 = 0x00; //
PIR2 = 0x00; //
m = PORTB; // чтение из регистра В
Lcd_Init(); // Инициализация дисплея
Lcd_Cmd(_LCD_CURSOR_OFF); // Отключить курсор
Lcd_Cmd(_LCD_CLEAR); // Очистить дисплей
Lcd_Out(1, 1, "WAIT..."); // Print text on LCD
Delay_ms(1000); // Пауза 1 сек
menuitem = 4; // Выбор начального пункта меню
Lcd_Cmd(_LCD_CLEAR); // Очистить дисплей
Lcd_Out(1, 1, device); // Print text on LCD
Lcd_Out(2, 1, ready); // Print text on LCD
// Конец инициализации
//*****************************************************************************
// Начало главного цикла программы
//*****************************************************************************
while(1){
//проверка нажатия кнопок
if (oldstate1 && Button(&PORTA, 0, 10, 0)) {
oldstate1 = 0;
// действия по нажатию кнопки 1 в зависимости от текущего пункта меню
switch (menuitem){
case 5 : pulses_def=pulses_def+100;
IntToStr(pulses_def, txt); // Print text on LCD
Lcd_Out(2, 1, txt); // Print text on LCD
break;
case 6 : pulses_def=pulses_def+10;
IntToStr(pulses_def, txt); // Print text on LCD
Lcd_Out(2, 1, txt); // Print text on LCD
break;
case 7 : pulses_def=pulses_def+1;
IntToStr(pulses_def, txt); // Print text on LCD
Lcd_Out(2, 1, txt); // Print text on LCD
break;
}
}
if (!oldstate1 && Button(&PORTA, 0, 10, 1)) oldstate1 = 1;
if (oldstate2 && Button(&PORTA, 1, 10, 0)) {
oldstate2 = 0;
// действия по нажатию кнопки 2 в зависимости от текущего пункта меню
switch (menuitem){
case 5 : pulses_def=pulses_def-100;
IntToStr(pulses_def, txt); // Print text on LCD
Lcd_Out(2, 1, txt); // Print text on LCD
break;
case 6 : pulses_def=pulses_def-10;
IntToStr(pulses_def, txt); // Print text on LCD
Lcd_Out(2, 1, txt); // Print text on LCD
break;
case 7 : pulses_def=pulses_def-1;
IntToStr(pulses_def, txt); // Print text on LCD
Lcd_Out(2, 1, txt); // Print text on LCD
break;
}
}
if (!oldstate2 && Button(&PORTA, 1, 10, 1)) oldstate2 = 1;
if (oldstate3 && Button(&PORTA, 2, 10, 0)) {
oldstate3 = 0;
// действия по нажатию кнопки 3 в зависимости от текущего пункта меню
switch (menuitem){
case 1 : Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, device); // Print text on LCD
Lcd_Out(2, 1, ready); // Print text on LCD
menuitem = 4;
break;
case 2 : program(); // выполнение программы
break;
case 4 : Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, pulses); // Print text on LCD
Lcd_Out(1, 8, "(1024)"); // Print text on LCD
Lcd_Out(2, 1, sot); // Print text on LCD
menuitem = 5;
break;
case 5 : Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, pulses); // Print text on LCD
Lcd_Out(2, 1, dec); // Print text on LCD
menuitem = 6;
break;
case 6 : Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, pulses); // Print text on LCD
Lcd_Out(2, 1, edi); // Print text on LCD
menuitem = 7;
break;
case 7 : menuitem = 2;
}
}
if (!oldstate3 && Button(&PORTA, 2, 10, 1)) oldstate3 = 1;
} // Конец главного цикла программы
}


