PIC16F1503
- Сообщения: 117
- Зарегистрирован: Ср ноя 05, 2014 19:04:31
Доброго всем времени суток! Очень нужна ваша помощь. С пиками работаю впервые да и вообще такую задачу решаю впервые. Есть данный контроллер ножки 3,7,8,9,10,11,12,13 сделаны как входы аналогового сигнала (на выводах 3,5В) от светодиодов. На каждую ножку подведено 2 светодиода. Задача состоит в том, что бы определить высокий уровень на данных входах, что бы сделать определенное действие. Небольшое исследование - закоротив 4 светодиода получили на всех входах 4.1В.
- Реклама
[uquote="DarkWolf",url="/forum/viewtopic.php?p=3134621#p3134621"]входы аналогового сигнала (на выводах 3,5В) от светодиодов. На каждую ножку подведено 2 светодиода[/uquote]Можете схемку изобразить, а то что-то вообще ничего не понятно? 
[uquote="DarkWolf",url="/forum/viewtopic.php?p=3134621#p3134621"]...сделаны как входы аналогового сигнала...[/uquote]
Схему сюда.
Схему сюда.
Docendo discimus
- Сообщения: 844
- Зарегистрирован: Пн апр 11, 2011 10:08:52
[uquote="DarkWolf",url="/forum/viewtopic.php?p=3134621#p3134621"]Доброго всем времени суток! Очень нужна ваша помощь. С пиками работаю впервые да и вообще такую задачу решаю впервые. Есть данный контроллер ножки 3,7,8,9,10,11,12,13 сделаны как входы аналогового сигнала (на выводах 3,5В) от светодиодов. На каждую ножку подведено 2 светодиода. Задача состоит в том, что бы определить высокий уровень на данных входах, что бы сделать определенное действие. Небольшое исследование - закоротив 4 светодиода получили на всех входах 4.1В.[/uquote]
Что-то не стыкуется, схема нужна!
Что-то не стыкуется, схема нужна!
- Реклама
- Сообщения: 117
- Зарегистрирован: Ср ноя 05, 2014 19:04:31
вот схема 
Да, я понял что с ADC работа. План действий таков:
1) Устанавливаю выводы как аналоговые входы
2) Через АЦП меряю какое напряжение и сравниваю его с нужным пределом.
Просто не знал что в пиках любой порт можно перевести как аналоговый, думал что с аналоговыми сигналами работает только порт A АЦП.
Буду благодарен в помощи настройки таймера. Даже в даташите не понимаю..
необходимо сформировать одиночный прямоугольный сигнал на ноге А5. При подаче питания высокий уровень длительностью 75мс, затем низкий уровень длительностью 25мс.
Да, я понял что с ADC работа. План действий таков:
1) Устанавливаю выводы как аналоговые входы
2) Через АЦП меряю какое напряжение и сравниваю его с нужным пределом.
Просто не знал что в пиках любой порт можно перевести как аналоговый, думал что с аналоговыми сигналами работает только порт A АЦП.
Буду благодарен в помощи настройки таймера. Даже в даташите не понимаю..
необходимо сформировать одиночный прямоугольный сигнал на ноге А5. При подаче питания высокий уровень длительностью 75мс, затем низкий уровень длительностью 25мс.
По таймеру: Как вариант, настройте TMR2 на 1mS и считайте время программно по прерыванию с TMR2.
Для настройки таймера надо знать частоту FOSC.
----
P.S.
А pdf на PIC16F1503, всё-таки, читать придётся...
Для настройки таймера надо знать частоту FOSC.
----
P.S.
А pdf на PIC16F1503, всё-таки, читать придётся...
Для PIC16F84A будет так:

Для PIC16F1503 нужно учесть наличие регистров ADCONx.
Спойлер
Код: Выделить всё
#include <pic.h>
unsigned char count;
void interrupt isr(void)
{
if(T0IF) // если переполнение TMR0
{
TMR0= 60; // предустановка на 25 мс
T0IF=0; // сбрасываем флаг переполнения таймера 0
if(++count > 3) count= 0; // наращиваем счетчик
if(count== 3) RA0= 0; // если такт 3, то сбрасываем выход
else RA0= 1; // если такты 0..2, то взводим выход
}
}
void main(void)
{
// запрещаем все прерывания
GIE= 0;
// настройка портов
PORTA = 0b00000000;
TRISA = 0b11111110; // RA0 - на выход
// инициализируем таймер
INTCON= 0b11100000;
OPTION= 0b00000100;
while(1); // бесконечный цикл
}Для PIC16F1503 нужно учесть наличие регистров ADCONx.
Docendo discimus
Если на контроллер подается 24В, то измерять не придется. Схема отвратительного качества. Контроллер очень непростой, это не 84а
Лучше умному тупить, чем тупому умничать
Курсовой надо полагать.anatol378 писал(а):...отвратительного качества...
[uquote="anatol378",url="/forum/viewtopic.php?p=3136224#p3136224"]...очень непростой...[/uquote]
Не боги горшки обжигают.
Docendo discimus
Если не читать документацию - все контроллеры не простые.anatol378 писал(а):Контроллер очень непростой
[uquote="Albert_V",url="/forum/viewtopic.php?p=3136410#p3136410"]..все контроллеры не простые.
[/uquote]
Оно ж понятно - человек просто набивает себе цену.
Оно ж понятно - человек просто набивает себе цену.
Docendo discimus
Насчет "Контроллер очень непростой" вероятно имелось ввиду, что для начала не помешало бы с обычными "среднемладшими" познакомиться, затем 18-ю серию проштудировать - а потом уже к этой разновидности приступать.

[uquote="BOB51",url="/forum/viewtopic.php?p=3137414#p3137414"]..для начала не помешало бы с обычными "среднемладшими"...[/uquote]
Как замечательно сказал. Даже если не применять всего что заложено (типа конфигурируемых логических ячеек или цифрового генератора), необходимо правильно сконфигурировать его, а для этого читать доки. Другого пути нет. Там немного в основном ДШ - 340 страниц.
Как замечательно сказал. Даже если не применять всего что заложено (типа конфигурируемых логических ячеек или цифрового генератора), необходимо правильно сконфигурировать его, а для этого читать доки. Другого пути нет. Там немного в основном ДШ - 340 страниц.
Лучше умному тупить, чем тупому умничать
- Сообщения: 117
- Зарегистрирован: Ср ноя 05, 2014 19:04:31
Уважаемые знатоки! Укажите куда копать.. не могу получить устойчивую работу ADC на PIC16F1503.
Вот текущий код:
void main(void)
{
// set up oscillator control register
OSCCONbits.IRCF = 0x0F; //set OSCCON IRCF bits to select OSC frequency=16Mhz
OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
LATA = 0x00; // turn all outputs off
LATC = 0x00;
// set timer
// PR2 = 0xFF;
// PIR1bits.TMR2IF = 0; // clear TMR2 interrupt flag
// T2CONbits.T2CKPS = 0x02; // TMR2 prescalar bits are both high; prescalar = 64
// T2CONbits.TMR2ON = 1; // TMR2 on
OPTION_REGbits.nWPUEN = 1; // all weak pullups are disabled
// PORT A5 - ВЫХОД, остальные ВХОДЫ
TRISAbits.TRISA0 = 1; // RA0 = nc (SPDAT)
TRISAbits.TRISA1 = 1; // RA0 = nc (SPCLK)
TRISAbits.TRISA2 = 1; // RA2 = Blue LED
//TRISAbits.TRISA3 = 1; // RA0 = nc (MLCR)
TRISAbits.TRISA4 = 1; // RA4 = nc
TRISAbits.TRISA5 = 0; // RA5 = nc
PORTA = 0x20; // Порт A5 устанавливаем 1.
ANSELA = 0x1F; // Все порты кроме A3 аналоговые
// Все порты С входы
TRISCbits.TRISC0 = 1; // RC0 =привет пишем комент на русском
TRISCbits.TRISC1 = 1; // RC1 =
TRISCbits.TRISC2 = 1; // RC2 =
TRISCbits.TRISC3 = 1; // RC3 =
TRISCbits.TRISC4 = 0;
TRISCbits.TRISC5 = 0;
PORTC = 0x00; //На всех входах 0
ANSELC = 0x0F; // С0 - С3 аналоговые
// Выбираем канал внутренего опорного напряжения
//Бит - 7 - Не используется, читается как 0
//Бит - 6-2- Выбор канала (11111 внутрение опорное напряжение)
//Бит 1- 1 - статус преобразования
//Бит 0 - 0 - включение преобразования
/// работаем с первым каналом
ADCON0 = 0b00000000;
ADCON1 = 0xb01110000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// Второй канал
ADCON0 = 0b00000100;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// 3 канал
ADCON0 = 0b00001000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
//Работаем с 4 каналом
ADCON0 = 0b00010000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// 5 канал
ADCON0 = 0b00010100;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// 6 канал
ADCON0 = 0b00011000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// Седьмой канал
ADCON0 = 0b00011100;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
if (countChanel <= 2 )
{
PORTA = 0x20; // Порт A5 устанавливаем 1.
mydelay_ms(87);
PORTA = 0; // Порт A5 устанавливаем 1.
mydelay_ms(25);
PORTA = 0x20; // Порт A5 устанавливаем 1.
}
while(1)
{
}
}
суть кода: анализирую напряжение на каналах, если напряжение больше 4 вольт то прибавляю счетчик. В итоге если счетчик меньше 2, то генерирую одиночный импульс. Правильно ли я перевожу полученные значения регистров в вольты. Небходимо с точностью хотя бы 1 знак после запятой..
Вот текущий код:
void main(void)
{
// set up oscillator control register
OSCCONbits.IRCF = 0x0F; //set OSCCON IRCF bits to select OSC frequency=16Mhz
OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
LATA = 0x00; // turn all outputs off
LATC = 0x00;
// set timer
// PR2 = 0xFF;
// PIR1bits.TMR2IF = 0; // clear TMR2 interrupt flag
// T2CONbits.T2CKPS = 0x02; // TMR2 prescalar bits are both high; prescalar = 64
// T2CONbits.TMR2ON = 1; // TMR2 on
OPTION_REGbits.nWPUEN = 1; // all weak pullups are disabled
// PORT A5 - ВЫХОД, остальные ВХОДЫ
TRISAbits.TRISA0 = 1; // RA0 = nc (SPDAT)
TRISAbits.TRISA1 = 1; // RA0 = nc (SPCLK)
TRISAbits.TRISA2 = 1; // RA2 = Blue LED
//TRISAbits.TRISA3 = 1; // RA0 = nc (MLCR)
TRISAbits.TRISA4 = 1; // RA4 = nc
TRISAbits.TRISA5 = 0; // RA5 = nc
PORTA = 0x20; // Порт A5 устанавливаем 1.
ANSELA = 0x1F; // Все порты кроме A3 аналоговые
// Все порты С входы
TRISCbits.TRISC0 = 1; // RC0 =привет пишем комент на русском
TRISCbits.TRISC1 = 1; // RC1 =
TRISCbits.TRISC2 = 1; // RC2 =
TRISCbits.TRISC3 = 1; // RC3 =
TRISCbits.TRISC4 = 0;
TRISCbits.TRISC5 = 0;
PORTC = 0x00; //На всех входах 0
ANSELC = 0x0F; // С0 - С3 аналоговые
// Выбираем канал внутренего опорного напряжения
//Бит - 7 - Не используется, читается как 0
//Бит - 6-2- Выбор канала (11111 внутрение опорное напряжение)
//Бит 1- 1 - статус преобразования
//Бит 0 - 0 - включение преобразования
/// работаем с первым каналом
ADCON0 = 0b00000000;
ADCON1 = 0xb01110000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// Второй канал
ADCON0 = 0b00000100;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// 3 канал
ADCON0 = 0b00001000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
//Работаем с 4 каналом
ADCON0 = 0b00010000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// 5 канал
ADCON0 = 0b00010100;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// 6 канал
ADCON0 = 0b00011000;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
__delay_us(5);
// Седьмой канал
ADCON0 = 0b00011100;
ADCON0bits.ADON = 1;
__delay_us(5);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
result = ((ADRESH * 205) + ADRESL);
}
if (result >= 4)
{
countChanel++;
}
if (countChanel <= 2 )
{
PORTA = 0x20; // Порт A5 устанавливаем 1.
mydelay_ms(87);
PORTA = 0; // Порт A5 устанавливаем 1.
mydelay_ms(25);
PORTA = 0x20; // Порт A5 устанавливаем 1.
}
while(1)
{
}
}
суть кода: анализирую напряжение на каналах, если напряжение больше 4 вольт то прибавляю счетчик. В итоге если счетчик меньше 2, то генерирую одиночный импульс. Правильно ли я перевожу полученные значения регистров в вольты. Небходимо с точностью хотя бы 1 знак после запятой..
После окончания преобразования сделайте вызов функции:
Только предварительно через #define Vdd_mV определите напряжение питания в мВ.
А откуда вы взяли 205 я так и не понял.
Для расчета удобно было бы подать напряжение питания 5.12 В, тогда result_v = 5 * result_adc - готовый результат в мВ.
Можно еще сделать привязку Vdd через внутреннее опорное 1.024 В, тогда еще с формулами поколдовать придется. В общем, варианты разные.
Код: Выделить всё
unsigned int calc_v(void)
{
unsigned int result_adc;
unsigned long result_v;
result_adc = ((ADRESH << 2) | ADRESL);
result_v = (unsigned long)Vdd_mV * result_adc;
return (result_v / 1024);
}
А откуда вы взяли 205 я так и не понял.
Для расчета удобно было бы подать напряжение питания 5.12 В, тогда result_v = 5 * result_adc - готовый результат в мВ.
Можно еще сделать привязку Vdd через внутреннее опорное 1.024 В, тогда еще с формулами поколдовать придется. В общем, варианты разные.
Каждый имеет право на свое личное ошибочное мнение.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
- Сообщения: 117
- Зарегистрирован: Ср ноя 05, 2014 19:04:31
Сделал как вы написали:
объявил #define Vdd_mV 4750
unsigned int ADC = 0;
и затем для каждого канала
ADRESH = 0;
ADRESL = 0;
ADCON0bits.ADON = 1;
__delay_us(10);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
ADC = calc_v();
}
if (ADC >= 4700)
{
countChanel++;
}
почему то в результате countChanel = 7 т.е считает что каждый канал соответствует условию. на деле же только 2 канала 4,7 вольта, остальные 4
объявил #define Vdd_mV 4750
unsigned int ADC = 0;
и затем для каждого канала
ADRESH = 0;
ADRESL = 0;
ADCON0bits.ADON = 1;
__delay_us(10);
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
{
ADC = calc_v();
}
if (ADC >= 4700)
{
countChanel++;
}
почему то в результате countChanel = 7 т.е считает что каждый канал соответствует условию. на деле же только 2 канала 4,7 вольта, остальные 4
Куда выводите результат? В смысле устройство отображения имеется?
Если есть возможность, для начала выводите голые значения result_adc для каждого канала, чтобы оценить правильность измерений.
А дальше видно будет.
Если есть возможность, для начала выводите голые значения result_adc для каждого канала, чтобы оценить правильность измерений.
А дальше видно будет.
Каждый имеет право на свое личное ошибочное мнение.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
- Сообщения: 117
- Зарегистрирован: Ср ноя 05, 2014 19:04:31
к сожалению устройства отображения нету.
проверяю в условии:
if (countChanel >= 2 )
{
PORTA = 0x20; // Порт A5 устанавливаем 1.
mydelay_ms(87);
PORTA = 0; // Порт A5 устанавливаем 1.
mydelay_ms(25);
PORTA = 0x20; // Порт A5 устанавливаем 1.
}
в итоге условие выполняется при countChanel = 7. А это значит что выполняется условие
if (ADC >= 4700)
{
countChanel++;
}
для каждого канала
Добавлено after 19 minutes 53 seconds:
в изначальной функции
unsigned int calc_v(void)
{
unsigned int result_adc;
unsigned long result_v;
result_adc = ((ADRESH << 2) | ADRESL);
result_v = (unsigned long)Vdd_mV * result_adc;
return (result_v / 1024);
}
присвоил result_adc = 0;
в итоге все верно. На выходе все каналы выдают 0;
проверяю в условии:
if (countChanel >= 2 )
{
PORTA = 0x20; // Порт A5 устанавливаем 1.
mydelay_ms(87);
PORTA = 0; // Порт A5 устанавливаем 1.
mydelay_ms(25);
PORTA = 0x20; // Порт A5 устанавливаем 1.
}
в итоге условие выполняется при countChanel = 7. А это значит что выполняется условие
if (ADC >= 4700)
{
countChanel++;
}
для каждого канала
Добавлено after 19 minutes 53 seconds:
в изначальной функции
unsigned int calc_v(void)
{
unsigned int result_adc;
unsigned long result_v;
result_adc = ((ADRESH << 2) | ADRESL);
result_v = (unsigned long)Vdd_mV * result_adc;
return (result_v / 1024);
}
присвоил result_adc = 0;
в итоге все верно. На выходе все каналы выдают 0;


