В предыдущей части занятия мы познакомились с микросхемой MCP3201, подключили нашу схему, а также настроили проект.
Если мы сейчас соберём и запустим наш проект, то мы на индикаторе ничего не увидим, так как индикатор у нас другой и подключен он к другим ножкам. Да и точки здесь у каждого разряда по умолчанию включатся, с этим нам также надо будет провести некоторую борьбу. И ещё: выводить мы будем число с двумя цифрами после точки, поэтому до точки может быть или одна или две цифры. Так вот, если будет одна, то самый левый разряд нам нужно будет погасить.
Поэтому перейдём в файл led.с и создадим глобальную переменную для числа
unsigned char n_count=0, R1=0, R2=0, R3=0, R4=0;
unsigned int num_gl;
Запомним число в функции ledprint
void ledprint(unsigned int number)
{
num_gl = number;
Также разряды у нашего индикатора расположены немного наоборот, устраним и это
num_gl = number;
R4 = number%10;
R3 = number%100/10;
R2 = number%1000/100;
R1 = number/1000;
Теперь идём в функцию перебора разрядов TIM0_Callback сначала в обработку самого старшего разряда и перепишем там код следующим образом
if(n_count==0)
{
PORTA &= ~0x08;
segchar(R1);
if(num_gl<1000) PORTB = 0xFF;
PORTA |= 0x21;
}
Теперь давайте разберёмся, что мы сделали.
Мы сначала обнулили ножку RA3, которая управляет самым младшим разрядом индикатора, чтобы погасить его, так как его мы зажигаем перед самым старшим, затем вызвали функцию, которая выставит ножки для цифры старшего разряда, затем погасим старший разряд, если у нас число трёхзначное, и по окончанию мы включим ножку RA0, которая и зажжёт нам старший разряд. Также первая двоечка в операнде гласит о том, что мы подадим высокий уровень на контакт точки, чтобы её отключить.
Далее идём в следующий разряд и поправим там код
else if(n_count==1)
{
PORTA &= ~0x01;
segchar(R2);
PORTB &= ~0x80;
PORTA |= 0x22;
}
Здесь мы точку, наоборот, включаем, выставив логический ноль на контакте RB7, так как точка нам в данном разряде будет нужна. Остальное всё подобно — гасим старший разряд и зажигаем следующий.
Следующий разряд:
else if(n_count==2)
{
PORTA &= ~0x02;
segchar(R3);
PORTA |= 0x24;
}
И последний:
else if(n_count==3)
{
PORTA &= ~0x04;
segchar(R4);
PORTA |= 0x28;
}
Теперь, если мы соберём код и прошьём контроллер, то будет всё нормально
Вернёмся в main.c и в функции main() настроим порт C для работы с шиной SPI
ledprint(1234);
TRISC=0x10;//RC4 Input (MISO)
Мы настроили все ножки порта на выход, за исключением той, которая отвечает за вход данных.
Теперь настроим модуль MSSP для работы с шиной SPI, задав режим SPI 0:0 согласно таблице, которую мы изучали ранее
TRISC=0x10;//RC4 Input (MISO)
// SSPM3:SSPM0 = 0000 (SPI Master mode, clock = 1 MHz)
// SKE=1, SKP=0 (SPI_MODE0)
// SMP=1 (Input data sampled at end of data output time)
// SSPEN= 1 (SPI Enabled)
SSPSTAT=0XC0;
SSPCON=0X30;
Выше функции main() добавим функцию приёма байта в шину SPI
//------------------------------------------------
static unsigned char SPI_Receive_byte(unsigned char data)
{
unsigned char temp;
SSPBUF=data;
while(!SSPIF);
SSPIF=0;
temp=SSPBUF;
return temp;
}
//------------------------------------------------
Здесь всё просто. мы отправляем в шину какие-нибудь данные, чтобы процесс обмена пошёл, ждём сброса флага, затем его устанавливаем и забрав данные из буфера, возвращаем их.
В функции main() добавим несколько локальных переменных
void main()
{
unsigned long dt1=0, dt2=0, res=0;
В бесконечном цикле примем сразу 2 байта, так как нам нужно принять именно 16 бит, опустив перед этим шину выбора, а после приёма её подняв
while(1)
{
CS_ON();
dt1 = SPI_Receive_byte(0xFF);
dt2 = SPI_Receive_byte(0xFF);
CS_OFF();
Соберём код, прошьём контроллер и посмотрим результат пока в программе логического анализа, включив там сначала три канала
Также настроим режим SPI вот таким образом
Сохраним настройки.
Теперь данные у нас отлично видятся и распознаются
Осталось нам эти данные обработать и вычислить с помощью них напряжение на ножке микросхемы.
Узнаем опорное напряжение, замерив его на первой ножке микросхемы
Сразу заодно померяем напряжение на 2 ножке — на входе АЦП
Запомним его и вернёмся в бесконечный цикл нашего проекта.
Напишем в комментарии, чтобы не забыть, получившееся опорное напряжение
CS_OFF();
//Vref = 4.58V
Путём несложных вычислений получим величину напряжение на входе АЦП
//Vref = 4.58V
res = (((dt1<<7)|(dt2>>1))&0x00000FFF)*457/4096;
Мы сдвинули полученные байты на нужные места, тем самым оставив только нужные биты, затем с помощью маски мы обнулили ненужные биты, оставив только 12 полезных бит, умножили на опорное напряжение, вернее на увеличенное в 100 раз и разделили на максимальное значение в 12-битного числа, увеличенное на 1. Так как у нас опорное напряжение умножено на 100, то мы получили и результат умноженный на 100. Поэтому мы просто поставим в нужном месте точку, что мы уже и сделали при настройке нашего индикатора. Тем самым мы избавились от работы с плавающей точкой, что значительно увеличивает быстродействие алгоритма.
Выведем на индикатор полученное число и добавим небольшую задержку
res = (((dt1<<7)|(dt2>>1))&0x00000FFF)*457/4096;
ledprint((unsigned int) res);
__delay_ms(200);
}
Соберём проект и прошьём контроллер. У нас получился вот такой результат
Как мы помним, мы именно такое число получили с помощью измерения мультиметром.
Отлично!
Для полноты эксперимента повращаем регулятор переменного резистора, сравнивая результаты на индикаторе мультиметра и на нашем индикаторе
Таким образом, мы получили вполне действующий, хоть и не очень функциональный цифровой вольтметр. Но главное не этот, а то, что мы теперь умеем работать с модулем MSSP в режиме SPI на приём. мы можем принимать по этой шине данные в режиме ведущего устройства.
Всем спасибо за внимание!
Предыдущая часть Программирование МК PIC Следующий урок
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Микросхема АЦП 12-разрядный MCP3201 — 5 шт
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добавить комментарий