Здравствуйте. Сделал счетчик импульсов энкодера. Импульсы подсчитываются, но при определенных оборотах вала энкодера счетчик зависает. Можно ли использовать для сброса МК сторожевой таймер и как? Слышал что на АВР вотчдог может запусткать программу с указанного места. Есть ли такая возможность на PIC?
Код программы прилагаю
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Описание переменных
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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;
} // Конец главного цикла программы
}
PIC16F887 проблемы с кодом
- Реклама
Re: PIC16F887 проблемы с кодом
Среда разработки MicroC PRO for PIC
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: PIC16F887 проблемы с кодом
Вач-дог может только сбрасывать контроллер, если его самого не сбросишь специальной инструкцией в течении определенного времени(т.е. работает как педаль мертвеца).
Re: PIC16F887 проблемы с кодом
Может быть так что контроллер виснет из-за большой подпрограммы обработки прерываний?
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 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; // разрешение прерываний
}
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: PIC16F887 проблемы с кодом
Запросто, если прерывания возникают чаще чем они могут быть обработаны.
Верней контроллер даже не зависает, просто выполняет команды основной программы по одной за время выполнения одного прерывания. Если прерывание обрабатывается милисекунды... то сам можешь прикинуть скорость выполнения основной программы.
Верней контроллер даже не зависает, просто выполняет команды основной программы по одной за время выполнения одного прерывания. Если прерывание обрабатывается милисекунды... то сам можешь прикинуть скорость выполнения основной программы.
- Реклама
- Dima Lerich
- Открыл глаза
- Сообщения: 44
- Зарегистрирован: Пт июл 19, 2013 10:19:19
- Откуда: Владивосток
Re: PIC16F887 проблемы с кодом
Надо попробовать поднять тактовую частоту МК. Уменьшить время обработки прерывания. Лучше и то и другое вместе. ПИКи вообще-то достаточно надежные зверьки.
Иногда получается спаять пару проводов...


