Operácie

Segmentový display TM1637: Rozdiel medzi revíziami

Z SensorWiki

Riadok 37: Riadok 37:
 
#include <avr/io.h>
 
#include <avr/io.h>
  
int main(void)
+
#define F_CPU 16000000UL  //define CPU frequency
 +
 
 +
//Required libraries
 +
#include <stdio.h>
 +
#include <avr/io.h>
 +
#include <util/delay.h>
 +
#include <avr/interrupt.h>
 +
 
 +
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
 +
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
 +
 
 +
#define CLK  PD5  // CLK -> pin 5 portD.5
 +
#define DIO  PD4  // DIO -> pin 4 portD.4
 +
 
 +
#define START_STOP_PIN PD2 // START_STOP_PIN -> pin 2 portD.2
 +
#define RESET_PIN PD3 // RESET_PIN -> pin 3 portD.3
 +
 
 +
 
 +
#define BIT_DELAY 100  //delay 100ms
 +
 
 +
//define for TM1637
 +
#define TM1637_I2C_COMM1    0x40
 +
#define TM1637_I2C_COMM2    0xC0
 +
#define TM1637_I2C_COMM3    0x80
 +
 
 +
 
 +
//
 +
//      A
 +
//    ---
 +
//  F |  | B
 +
//    -G-
 +
//  E |  | C
 +
//    ---
 +
//      D
 +
const uint8_t digitToSegment[] = {
 +
// XGFEDCBA
 +
0b00111111,    // 0
 +
0b00000110,    // 1
 +
0b01011011,    // 2
 +
0b01001111,    // 3
 +
0b01100110,    // 4
 +
0b01101101,    // 5
 +
0b01111101,    // 6
 +
0b00000111,    // 7
 +
0b01111111,    // 8
 +
0b01101111,    // 9
 +
0b01110111,    // A
 +
0b01111100,    // b
 +
0b00111001,    // C
 +
0b01011110,    // d
 +
0b01111001,    // E
 +
0b01110001    // F
 +
};
 +
 
 +
static const uint8_t minusSegments = 0b01000000;
 +
 
 +
uint8_t brightness = (0x7 & 0x7) | 0x08;
 +
 
 +
void displayInit(){
 +
clear_bit(DDRD,CLK);  // set CLK as input
 +
set_bit(PORTD,CLK);  // CLK as input pull-up on
 +
 +
clear_bit(DDRD,DIO);  // set DIO as input
 +
set_bit(PORTD,DIO);  // DIO as input pull-up on
 +
}
 +
 
 +
void startCom(){
 +
set_bit(DDRD,DIO);  // set DIO as output
 +
clear_bit(PORTD,DIO);  // set DIO as output
 +
_delay_us(BIT_DELAY);
 +
}
 +
 
 +
void stopCom(){
 +
set_bit(DDRD,DIO);  // set DIO as output
 +
clear_bit(PORTD,DIO);  // set DIO as output
 +
_delay_us(BIT_DELAY);
 +
 +
clear_bit(DDRD,CLK);  // set CLK as input
 +
set_bit(PORTD,CLK);  // CLK as input pull-up on
 +
_delay_us(BIT_DELAY);
 +
 +
clear_bit(DDRD,DIO);  // set DIO as input
 +
set_bit(PORTD,DIO);  // DIO as input pull-up on
 +
_delay_us(BIT_DELAY);
 +
}
 +
 
 +
int displayWriteByte(uint8_t byte){
 +
uint8_t data = byte;
 +
 +
// 8 Data Bits
 +
for(uint8_t i = 0; i < 8; i++) {
 +
// CLK low
 +
set_bit(DDRD,CLK);
 +
clear_bit(PORTD,CLK);
 +
_delay_us(BIT_DELAY);
 +
 
 +
// Set data bit
 +
if (data & 0x01){
 +
clear_bit(DDRD,DIO);  // set DIO as input
 +
set_bit(PORTD,DIO);  // DIO as input pull-up on
 +
} else{
 +
set_bit(DDRD,DIO);  // set DIO as output
 +
clear_bit(PORTD,DIO);
 +
}
 +
 +
 
 +
_delay_us(BIT_DELAY);
 +
 
 +
// CLK high
 +
clear_bit(DDRD,CLK);  // set CLK as input
 +
set_bit(PORTD,CLK);  // CLK as input pull-up on
 +
_delay_us(BIT_DELAY);
 +
data = data >> 1;
 +
}
 +
 
 +
// Wait for acknowledge
 +
// CLK to zero
 +
set_bit(DDRD,CLK);  // set CLK as output
 +
clear_bit(PORTD,CLK);
 +
 +
clear_bit(DDRD,DIO);  // set DIO as input
 +
set_bit(PORTD,DIO);  // DIO as input pull-up on
 +
_delay_us(BIT_DELAY);
 +
 
 +
// CLK to high
 +
clear_bit(DDRD,CLK);  // set CLK as input
 +
set_bit(PORTD,CLK);  // CLK as input pull-up on
 +
_delay_us(BIT_DELAY);
 +
uint8_t ack = !bit_is_clear(PIND, DIO);
 +
if (ack == 0)
 +
set_bit(DDRD,DIO);  // set DIO as output
 +
clear_bit(PORTD,DIO);
 +
 +
 
 +
 
 +
_delay_us(BIT_DELAY);
 +
set_bit(DDRD,CLK);  // set CLK as output
 +
clear_bit(PORTD,CLK);
 +
_delay_us(BIT_DELAY);
 +
 
 +
return ack;
 +
}
 +
 
 +
void displayShowDots(uint8_t dots, uint8_t* digits){
 +
for(int i = 0; i < 4; ++i)
 +
{
 +
digits[i] |= (dots & 0x80);
 +
dots <<= 1;
 +
}
 +
 +
}
 +
 
 +
uint8_t displayEncodeDigit(uint8_t digit){
 +
return digitToSegment[digit & 0x0f];
 +
}
 +
 
 +
void displaySetSegments(const uint8_t segments[], uint8_t length, uint8_t pos){
 +
// Write COMM1
 +
startCom();
 +
displayWriteByte(TM1637_I2C_COMM1);
 +
stopCom();
 +
 
 +
// Write COMM2 + first digit address
 +
startCom();
 +
displayWriteByte(TM1637_I2C_COMM2 + (pos & 0x03));
 +
 
 +
// Write the data bytes
 +
for (uint8_t k=0; k < length; k++)
 +
displayWriteByte(segments[k]);
 +
 
 +
stopCom();
 +
 
 +
// Write COMM3 + brightness
 +
startCom();
 +
displayWriteByte(TM1637_I2C_COMM3 + (brightness & 0x0f));
 +
stopCom();
 +
}
 +
 
 +
void displayClear(){
 +
uint8_t data[] = { 0, 0, 0, 0 };
 +
displaySetSegments(data, 4, 0);
 +
}
 +
 
 +
// Function to display a number in a given base with custom options
 +
void displayShowNumberBaseEx(int8_t base, uint16_t num, uint8_t dots, const int leading_zero,
 +
uint8_t length, uint8_t pos)
 +
{
 +
int negative = 0; //false
 +
if (base < 0) {
 +
base = -base;
 +
negative = 1; //true
 +
}
 +
 
 +
 
 +
uint8_t digits[4];
 +
 
 +
if (num == 0 && !leading_zero) {
 +
// Singular case - take care separately
 +
for(uint8_t i = 0; i < (length-1); i++)
 +
digits[i] = 0;
 +
digits[length-1] = displayEncodeDigit(0);
 +
}
 +
else {
 +
//uint8_t i = length-1;
 +
//if (negative) {
 +
// // Negative number, show the minus sign
 +
//    digits[i] = minusSegments;
 +
// i--;
 +
//}
 +
 +
for(int i = length-1; i >= 0; --i)
 +
{
 +
uint8_t digit = num % base;
 +
 +
if (digit == 0 && num == 0 && leading_zero == 0)
 +
// Leading zero is blank
 +
digits[i] = 0;
 +
else
 +
digits[i] = displayEncodeDigit(digit);
 +
 +
if (digit == 0 && num == 0 && negative) {
 +
digits[i] = minusSegments;
 +
negative = 0;
 +
}
 +
 
 +
num /= base;
 +
}
 +
}
 +
 +
if(dots != 0)
 +
{
 +
displayShowDots(dots, digits);
 +
}
 +
 +
displaySetSegments(digits, length, pos);
 +
}
 +
 
 +
// ak dots 0x40 - dvojbodka v strede svieti
 +
// ak dots 0 - dvojbodka v strede nesvieti
 +
 
 +
// Function to display a decimal number with custom options
 +
void displayShowNumberDecEx(int num, uint8_t dots, const int leading_zero,
 +
uint8_t length, uint8_t pos){
 +
displayShowNumberBaseEx(num < 0? -10 : 10, num < 0? -num : num, dots, leading_zero, length, pos);
 +
}
 +
 
 +
// Function to display a decimal number with default options
 +
void displayShowNumberDec(int num, const int leading_zero, uint8_t length, uint8_t pos){
 +
displayShowNumberDecEx(num,  0x40, leading_zero, length, pos);
 +
}
 +
 
 +
// Function to initialize the buttons
 +
void initButtons(){
 +
clear_bit(DDRD, START_STOP_PIN);  // set START_STOP_PIN as input
 +
set_bit(PORTD, START_STOP_PIN);  // START_STOP_PIN as input pull-up on
 +
 +
clear_bit(DDRD, RESET_PIN);  // set RESET_PIN as input
 +
set_bit(PORTD, RESET_PIN);  // RESET_PIN as input pull-up on
 +
}
 +
 
 +
 
 +
volatile unsigned int elapsedTime = 0;
 +
volatile int running = 0;
 +
 
 +
// Timer1 overflow interrupt service routine
 +
ISR (TIMER1_OVF_vect)
 +
{
 +
elapsedTime++;
 +
if(elapsedTime > 9999) elapsedTime=0;
 +
TCNT1 = 0xFF63;          // initialize (CLEAR) counter
 +
}
 +
 
 +
// External interrupt 0 (start/stop button)
 +
ISR (INT0_vect)
 +
{
 +
_delay_ms(10);
 +
if(bit_is_clear(PIND,START_STOP_PIN)){
 +
running = !running;
 +
TCCR1B = running ? 0b00000000 : 0b00000101;
 +
}
 +
_delay_ms(10);
 +
}
 +
 
 +
// External interrupt 1 (reset button)
 +
ISR (INT1_vect)
 
{
 
{
  unsigned int measuredValue;
+
_delay_ms(10);
 +
if(bit_is_clear(PIND,RESET_PIN)){
 +
elapsedTime = 0;
 +
}
 +
_delay_ms(10);
 +
}
  
  while (1)
+
int main(void){
  {
+
    /* relax  */
+
    displayInit();
  }
+
displayClear();
 +
 +
initButtons();
 +
 +
displayShowNumberDec(0, 1, 4, 0); // pociatocny stav 00:00
 +
 +
TCNT1 = 0xFF63;          // initialize (CLEAR) counter
 +
TCCR1B = 0b00000000;      // turn off timer
 +
TIFR1 = (1<<TOV1); // clear Timer 1 Overflow Flag
 +
TIMSK1 = (1<<TOIE1); //overflow input enable
 +
 +
EIMSK = 0b00000011; //enable int0 and int1
 +
EICRA = 0b00001010; //detect falling edge on both pins
 +
 +
sei(); // enable interrupts
 +
 +
set_bit(DDRB,PB5);
  
  return(0);
+
    while (1) {
 +
displayShowNumberDec(elapsedTime, 1, 4, 0);
 +
    }
 +
 +
return 0;
 
}
 
}
 +
  
 
</source></tab>
 
</source></tab>

Verzia zo dňa a času 13:25, 7. jún 2023

Záverečný projekt predmetu MIPS / LS2023 - Juraj Štefánik


Zadanie

Segmentový display TM1637 - napíšte rutiny na zobrazenie čísla a času na tomto displeji. Predvedenie funkcie si vymyslite, napr. stopky a pod.

Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie

Vývojová doska ACROB.

Literatúra:


Analýza a opis riešenia

Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami...

RGB LED.

Nezabudnite doplniť schému zapojenia!

Schéma zapojenia LCD displeja.


Algoritmus a program

Algoritmus programu je....


#include <avr/io.h>

#define F_CPU 16000000UL  //define CPU frequency

//Required libraries
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))

#define CLK  PD5  // CLK -> pin 5 portD.5
#define DIO  PD4  // DIO -> pin 4 portD.4

#define START_STOP_PIN PD2 // START_STOP_PIN -> pin 2 portD.2
#define RESET_PIN PD3 // RESET_PIN -> pin 3 portD.3


#define BIT_DELAY 100  //delay 100ms

//define for TM1637
#define TM1637_I2C_COMM1    0x40
#define TM1637_I2C_COMM2    0xC0
#define TM1637_I2C_COMM3    0x80


//
//      A
//     ---
//  F |   | B
//     -G-
//  E |   | C
//     ---
//      D
const uint8_t digitToSegment[] = {
	// XGFEDCBA
	0b00111111,    // 0
	0b00000110,    // 1
	0b01011011,    // 2
	0b01001111,    // 3
	0b01100110,    // 4
	0b01101101,    // 5
	0b01111101,    // 6
	0b00000111,    // 7
	0b01111111,    // 8
	0b01101111,    // 9
	0b01110111,    // A
	0b01111100,    // b
	0b00111001,    // C
	0b01011110,    // d
	0b01111001,    // E
	0b01110001     // F
};

static const uint8_t minusSegments = 0b01000000;

uint8_t brightness = (0x7 & 0x7) | 0x08;

void displayInit(){
	clear_bit(DDRD,CLK);  // set CLK as input
	set_bit(PORTD,CLK);  // CLK as input pull-up on
	
	clear_bit(DDRD,DIO);  // set DIO as input
	set_bit(PORTD,DIO);  // DIO as input pull-up on
}

void startCom(){
	set_bit(DDRD,DIO);  // set DIO as output
	clear_bit(PORTD,DIO);  // set DIO as output
	_delay_us(BIT_DELAY);
}

void stopCom(){
	set_bit(DDRD,DIO);  // set DIO as output
	clear_bit(PORTD,DIO);  // set DIO as output
	_delay_us(BIT_DELAY);
	
	clear_bit(DDRD,CLK);  // set CLK as input
	set_bit(PORTD,CLK);  // CLK as input pull-up on
	_delay_us(BIT_DELAY);
	
	clear_bit(DDRD,DIO);  // set DIO as input
	set_bit(PORTD,DIO);  // DIO as input pull-up on
	_delay_us(BIT_DELAY);
}

int displayWriteByte(uint8_t byte){
	uint8_t data = byte;
	
	// 8 Data Bits
	for(uint8_t i = 0; i < 8; i++) {
		// CLK low
		set_bit(DDRD,CLK);
		clear_bit(PORTD,CLK);
		_delay_us(BIT_DELAY);

		// Set data bit
		if (data & 0x01){
			clear_bit(DDRD,DIO);  // set DIO as input
			set_bit(PORTD,DIO);  // DIO as input pull-up on
		} else{
			set_bit(DDRD,DIO);  // set DIO as output
			clear_bit(PORTD,DIO);
		}
		

		_delay_us(BIT_DELAY);

		// CLK high
		clear_bit(DDRD,CLK);  // set CLK as input
		set_bit(PORTD,CLK);  // CLK as input pull-up on
		_delay_us(BIT_DELAY);
		data = data >> 1;
	}

	// Wait for acknowledge
	// CLK to zero
	set_bit(DDRD,CLK);  // set CLK as output
	clear_bit(PORTD,CLK);
	
	clear_bit(DDRD,DIO);  // set DIO as input
	set_bit(PORTD,DIO);  // DIO as input pull-up on
	_delay_us(BIT_DELAY);

	// CLK to high
	clear_bit(DDRD,CLK);  // set CLK as input
	set_bit(PORTD,CLK);  // CLK as input pull-up on
	_delay_us(BIT_DELAY);
	uint8_t ack = !bit_is_clear(PIND, DIO);
	if (ack == 0)
	set_bit(DDRD,DIO);  // set DIO as output
	clear_bit(PORTD,DIO);
	


	_delay_us(BIT_DELAY);
	set_bit(DDRD,CLK);  // set CLK as output
	clear_bit(PORTD,CLK);
	_delay_us(BIT_DELAY);

	return ack;
}

void displayShowDots(uint8_t dots, uint8_t* digits){
	for(int i = 0; i < 4; ++i)
	{
		digits[i] |= (dots & 0x80);
		dots <<= 1;
	}
	
}

uint8_t displayEncodeDigit(uint8_t digit){
	return digitToSegment[digit & 0x0f];
}

void displaySetSegments(const uint8_t segments[], uint8_t length, uint8_t pos){
	// Write COMM1
	startCom();
	displayWriteByte(TM1637_I2C_COMM1);
	stopCom();

	// Write COMM2 + first digit address
	startCom();
	displayWriteByte(TM1637_I2C_COMM2 + (pos & 0x03));

	// Write the data bytes
	for (uint8_t k=0; k < length; k++)
	displayWriteByte(segments[k]);

	stopCom();

	// Write COMM3 + brightness
	startCom();
	displayWriteByte(TM1637_I2C_COMM3 + (brightness & 0x0f));
	stopCom();
}

void displayClear(){
	uint8_t data[] = { 0, 0, 0, 0 };
	displaySetSegments(data, 4, 0);
}

// Function to display a number in a given base with custom options
void displayShowNumberBaseEx(int8_t base, uint16_t num, uint8_t dots, const int leading_zero,
uint8_t length, uint8_t pos)
{
	int negative = 0; //false
	if (base < 0) {
		base = -base;
		negative = 1; //true
	}


	uint8_t digits[4];

	if (num == 0 && !leading_zero) {
		// Singular case - take care separately
		for(uint8_t i = 0; i < (length-1); i++)
		digits[i] = 0;
		digits[length-1] = displayEncodeDigit(0);
	}
	else {
		//uint8_t i = length-1;
		//if (negative) {
		//	// Negative number, show the minus sign
		//    digits[i] = minusSegments;
		//	i--;
		//}
		
		for(int i = length-1; i >= 0; --i)
		{
			uint8_t digit = num % base;
			
			if (digit == 0 && num == 0 && leading_zero == 0)
			// Leading zero is blank
			digits[i] = 0;
			else
			digits[i] = displayEncodeDigit(digit);
			
			if (digit == 0 && num == 0 && negative) {
				digits[i] = minusSegments;
				negative = 0;
			}

			num /= base;
		}
	}
	
	if(dots != 0)
	{
		displayShowDots(dots, digits);
	}
	
	displaySetSegments(digits, length, pos);
}

// ak dots 0x40 - dvojbodka v strede svieti
// ak dots 0 - dvojbodka v strede nesvieti

// Function to display a decimal number with custom options
void displayShowNumberDecEx(int num, uint8_t dots, const int leading_zero,
uint8_t length, uint8_t pos){
	displayShowNumberBaseEx(num < 0? -10 : 10, num < 0? -num : num, dots, leading_zero, length, pos);
}

// Function to display a decimal number with default options
void displayShowNumberDec(int num, const int leading_zero, uint8_t length, uint8_t pos){
	displayShowNumberDecEx(num,  0x40, leading_zero, length, pos);
}

// Function to initialize the buttons
void initButtons(){
	clear_bit(DDRD, START_STOP_PIN);  // set START_STOP_PIN as input
	set_bit(PORTD, START_STOP_PIN);  // START_STOP_PIN as input pull-up on
	
	clear_bit(DDRD, RESET_PIN);  // set RESET_PIN as input
	set_bit(PORTD, RESET_PIN);  // RESET_PIN as input pull-up on
}


volatile unsigned int elapsedTime = 0;
volatile int running = 0;

// Timer1 overflow interrupt service routine
ISR (TIMER1_OVF_vect)
{
	elapsedTime++;
	if(elapsedTime > 9999) elapsedTime=0;
	TCNT1 = 0xFF63;           // initialize (CLEAR) counter
}

// External interrupt 0 (start/stop button)
ISR (INT0_vect)
{
	_delay_ms(10);
	if(bit_is_clear(PIND,START_STOP_PIN)){
		running = !running;
		TCCR1B = running ? 0b00000000 : 0b00000101;
	}
	_delay_ms(10);
}

// External interrupt 1 (reset button)
ISR (INT1_vect)
{
	_delay_ms(10);
	if(bit_is_clear(PIND,RESET_PIN)){
		elapsedTime = 0;
	}
	_delay_ms(10);
}

int main(void){
	
    displayInit();
	displayClear();
	
	initButtons();
	
	displayShowNumberDec(0, 1, 4, 0); // pociatocny stav 00:00
	
	TCNT1 = 0xFF63;           // initialize (CLEAR) counter
	TCCR1B = 0b00000000;      // turn off timer
	TIFR1 = (1<<TOV1); // clear Timer 1 Overflow Flag
	TIMSK1 = (1<<TOIE1); //overflow input enable
	
	EIMSK = 0b00000011; //enable int0 and int1
	EICRA = 0b00001010; //detect falling edge on both pins
	
	sei();  // enable interrupts
	
	set_bit(DDRB,PB5);

    while (1) {
		displayShowNumberDec(elapsedTime, 1, 4, 0);
    }
	
	return 0;
}
#include <avr/io.h>

void adc_init(void);                                   // A/D converter initialization

unsigned int adc_read(char a_pin);

Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:

Zdrojový kód: zdrojaky.zip


Overenie

Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku záverečnej obrazovky pred resetom. Vypísaný je tu priemerný čas a najlepší čas.

Aplikácia.

Video:

Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.