Задача: Отобразить цифры от 0 до 9 на семисегментном индикаторе
Исходный материал: PIC16f628a, семисегментный индикатор с общим катодом, breadboard
В этом эксперименте я пойду немного не стандартным путем и не буду использовать 8 ног мк чтобы подключить один лишь индикатор, жалко ног столько зря терять. Поэтому добавим к схеме еще сдвиговый регистр, например 74нс164, очень полезная штука. Теперь вместо восьми ног нам понадобится всего 4:
- На тактирование.
- На сброс.
- На данные.
- На питающий транзистор.
Экономия – налицо! Работу сдвигового регистра я описывать не буду, всегда можно заглянуть в даташит – там все предельно понятно расписано. Для начала соберем тестовую схему, а потом напишем код, который будет отображать наши цифры с периодом 1 с (этакий простой секундомерчик до 10 секунд).
Итак для начала соберем тестовую схему:
Кнопку я добавил, чтобы четко определять старт программы. Ну и еще резистор R11 по сути там не нужен, но протеус, собака такая, отказывался нормально моделировать без него. В принципе сложного ничего нету, единственный момент, на который стоит обратить внимание – это то, что я с целью экономии памяти расположил массивы чисел в ROM.
#include htc.h #define _XTAL_FREQ 4000000 #define CK RB2 #define RESET RB1 #define DATA RB3 #define TRIG RB7 __CONFIG(MCLREN &UNPROTECT & WDTDIS); void tick() { CK = 1; __delay_us(100); CK = 0; __delay_us(100); } void vpih(unsigned char digit[8]) { unsigned char i=0; TRIG = 0; for (i=0;i<8;i++) { DATA = digit[i]; tick(); } TRIG = 1; } const char point[8] = {1,0,0,0,0,0,0,0}; // Точка const char one[8] = {0,0,0,0,0,1,1,0}; // Один const char two[8] = {0,1,0,1,1,0,1,1}; // Два const char three[8] = {0,1,0,0,1,1,1,1}; // Три const char four[8] = {0,1,1,0,0,1,1,0}; // Четыре const char five[8] = {0,1,1,0,1,1,0,1}; // Пять const char six[8] = {0,1,1,1,1,1,0,1}; // Шесть const char seven[8] = {0,0,0,0,0,1,1,1}; // Семь const char eight[8] = {0,1,1,1,1,1,1,1}; // Восемь const char nine[8] = {0,1,1,0,1,1,1,1}; // Девять const char zero[8] = {0,0,1,1,1,1,1,1}; // Ноль void main() { unsigned char i=0; TRISB = 0b00000001; DATA = 0; RESET = 0; tick(); RESET = 1; for (;;) { if (RB0 == 0) { __delay_ms(30); if (RB0 == 0) { vpih(zero); for(i=0;i<10;i++){ __delay_ms(100); } vpih(one); for(i=0;i<10;i++){ __delay_ms(100); } vpih(two); for(i=0;i<10;i++){ __delay_ms(100); } vpih(three); for(i=0;i<10;i++){ __delay_ms(100); } vpih(four); for(i=0;i<10;i++){ __delay_ms(100); } vpih(five); for(i=0;i<10;i++){ __delay_ms(100); } vpih(six); for(i=0;i<10;i++){ __delay_ms(100); } vpih(seven); for(i=0;i<10;i++){ __delay_ms(100); } vpih(eight); for(i=0;i<10;i++){ __delay_ms(100); } vpih(nine); for(i=0;i<10;i++){ __delay_ms(100); } } } } }
PS. В этой программе хреново используется массив, это я в начале своего обучения допустил такой косячок, но править мне уже лень 🙂
Исходники здесь
почерпнул много нового
Смахивает на какой то быдлокод, мне для отображения одной цифры достаточно одной ячейки чар,а тут целых восемь!
Разговор шел про экономию памяти, а на самом деле ее больше затрачено, чем необходимо.Только оперативную сэкономили.
так и есть, для всех цифр достаточно было бы одного определения массива (о чем я кстати в конце написал)
const unsigned char digits[9] =
{0b10000000,
0b00000110,
….
};
Данная статья писалась практически в самом начале изучения мк мной, так что соглашусь, в данном виде это быдлокод и надо бы ее подправить, так что наверное даже спасибо за критику.
Если прописать таким образом массив ,
const unsigned char digits[9] = {
0b10000000,
0b00000110,
…. };
тогда как будет воспринимать сдвиговый регистр нули и единицы? У меня таким образом ничего не получилось. Зато удачно получилось с двумерным массивом. Или я где ошибся и это нерационально? Код у меня этот работает отлично:
const unsigned char digit[10][8]={
{0,0,1,1,1,1,1,1}, //0
{0,0,0,0,0,1,1,0}, //1
{0,1,0,1,1,0,1,1}, //2
{0,1,0,0,1,1,1,1}, //3
{0,1,1,0,0,1,1,0}, //4
{0,1,1,0,1,1,0,1}, //5
{0,1,1,1,1,1,0,1}, //6
{0,0,0,0,0,1,1,1}, //7
{0,1,1,1,1,1,1,1}, //8
{0,1,1,0,1,1,1,1}, //9
};
void main() {
TRISB = 0b00000001;
DATA = 0;
RESET = 0;
RESET = 1;
for (;;){
for (n=0; n<10; n++){
for (i=0; i<8; i++){
DATA = digit[n][i];
tick();
}
__delay_ms(50);
}
}
}
Он будет их воспринимать ровно так как вы ему скажете, модернизируйте функцию до уровня определения каждого бита и все будет ок.
Двумерный массив это еще хуже чем моя первая версия и я не понимаю зачем его здесь в принципе использовать.
Повторяем 8 раз
1. Взяли последний бит
2. Выпихнули
3. Сдвинули байт на одну позицию вправо
Здравствуйте.
В строке №17 наверное, ошибка – for(i=0;i<8;i++) {
Возможно, там должно быть – for (i=0;i<8;i++) {
Исправьте мое сообщения.
В строке №17 наверное, ошибка – for(i=0;i<8;i++) {
Возможно, там должно быть – for (i=0;i<8;i++) {
Указал на ошибку в своем сообщении, но при загрузке она автоматически исправляется. Уже третий раз не буду указывать место ошибки Вы, наверное, сами найдете.
Это просто на старом хостинге у меня был другой плагин для подсветки кода, и он служебные символы часто в html конвертил.
DOBROE VREMYA SUTOK . HOTEL SPROSIT NEEXPERIMENTIROVALI SVETODIODNIMI MATRISAMI 8X6 ILI 8X8 ?
Доброе,
неа, не доводилось.
Уведомление: Pic Lab, PIC16, Experiment #4: 7 segment display | diymicro.org