Configuration Wizard в KEIL. Ассемблер А51, подбор битовых масок для вывода на семисегментный индикатор

  Что такое Configuration Wizard (мастер конфигураций) в KEIL? Это псевдокод написанный в комментариях и оформленный спецтегами. При наличии такого кода в проекте появляется дополнительная вкладка «Configuration Wizard».
  На странице помощи по Configuration Wizard упор сделан на С программировании. Но мастер конфигураций легко встраивается и в чисто ассемблерные проекты. При этом следует придерживаться ассемблерной орфографии. Ниже приведен пример подобного мастера.

  Семисегментный индикатор часто подключают к шинам контроллера руководствуясь только простотой разводки печатной платы. Поэтому вывод на индикатор требует соответствующей кодировки выводимых символов. Облегчить их получение и помогает мастер конфигураций.
  Подключив данный файл в проект (CW_DISPBITS.a51) и открыв его, щелкаем по закладке «Configuration Wizard», затем по кнопке «Expand All».



Код мастера:

;= Битовые маски для семисегментного дисплея ==================;
;            A
;            --
;          F|  |B
;           G--
;          E|  |C
;            -- .H
;            D
;
;  *** <<< Use Configuration Wizard in Context Menu >>> ***
;- Header ------------------------------------------------------;
; <h> Make Display Segments
;- Segment A ---------------------------------------------------;
; 	<e> Enable Segment A
;       <i> Enable Segment A for making
Enb_A EQU  0	 
; 		<o> Bit A
;   	        <i> Top-Middle segment
; 		<0=> A=0, - - - - - - - X
; 		<1=> A=1, - - - - - - X -
; 		<2=> A=2, - - - - - X - -
; 		<3=> A=3, - - - - X - - -
; 		<4=> A=4, - - - X - - - -
; 		<5=> A=5, - - X - - - - -
; 		<6=> A=6, - X - - - - - -
; 		<7=> A=7, X - - - - - - -
Bit_A EQU  0
IF (Enb_A = 1)
Seg_A EQU  Bit_A << 1
ELSE
Seg_A EQU  0
ENDIF
; 	</e>
;- Segment B ---------------------------------------------------;
;- Segment C ---------------------------------------------------;
;- Segment D ---------------------------------------------------;
;- Segment E ---------------------------------------------------;
;- Segment F ---------------------------------------------------;
;- Segment G ---------------------------------------------------;
;- Segment H ---------------------------------------------------;
; </h>
;  *** <<< end of configuration section >>> ***

  После тега <h> идет общий заголовок «Make Display Segments» мастера. Ему должен соответствовать закрывающий тег </h>.
  Затем после тега <e> идет группа настроек с общим разрешающим чекбоксом. Если чекбокс не отмечен, заголовок группы и все входящие в группу настройки будут серыми (неактивными). Здесь также требуется закрывающий тег </e>. Состояние чекбокса отображается в константе Enb_A. Пока чекбокс не отмечен — Enb_A EQU 0, если отмечен — Enb_A EQU 1.
  В группу входит только одна настройка — после тега <o> размещен выпадающий список. Результат выбора — индекс выбранной строки. Закрывающий тег не требуется. Состояние списка отображается в константе Bit_A.
Строки после тега <i> — подсказки. Закрывающий тег не требуется.
  Далее средствами условной компиляции обрабатываются константы Enb_A и Bit_A. Если чекбокс отмечен, формируется требуемая битовая маска Seg_A, если нет — маска содержит 0.
Маски остальных сегментов формируются аналогично. Конец мастера.

  Затем из масок отдельных сегментов формируются маски символов для семисегментного индикатора. Общепринятое начертание цифр:

;-- Digits -----------------------------------------------------;
CH_0	EQU		Seg_A | Seg_B | Seg_C | Seg_D | Seg_E | Seg_F
CH_1	EQU		Seg_B | Seg_C
CH_2	EQU		Seg_A | Seg_B | Seg_D | Seg_E | Seg_G 
CH_3	EQU		Seg_A | Seg_B | Seg_C | Seg_D | Seg_G
CH_4	EQU		Seg_B | Seg_C | Seg_F | Seg_G 
CH_5	EQU		Seg_A | Seg_C | Seg_D | Seg_F | Seg_G
CH_6	EQU		Seg_A | Seg_C | Seg_D | Seg_E | Seg_F | Seg_G 
CH_7	EQU		Seg_A | Seg_B | Seg_C 
CH_8	EQU		Seg_A | Seg_B | Seg_C | Seg_D | Seg_E | Seg_F | Seg_G 
CH_9	EQU		Seg_A | Seg_B | Seg_C | Seg_D | Seg_F | Seg_G 

  С символами латинского алфавита сложнее, некоторые не так просто отразить на семисегментном индикаторе. Вот один из вариантов:



И его кодировки:

;-- Symbols ---------------------------------------------------	;
CH_A	EQU		Seg_A | Seg_B | Seg_C | Seg_E | Seg_F
CH_B	EQU		Seg_C | Seg_D | Seg_E | Seg_F | Seg_G
CH_C	EQU		Seg_A | Seg_D | Seg_E | Seg_F 
CH_D	EQU		Seg_B | Seg_C | Seg_D | Seg_E | Seg_G
CH_E	EQU		Seg_A | Seg_D | Seg_E | Seg_F | Seg_G
CH_F	EQU		Seg_A | Seg_E | Seg_F | Seg_G
CH_G	EQU		Seg_A | Seg_C | Seg_D | Seg_E | Seg_F
CH_H	EQU		Seg_B | Seg_C | Seg_E | Seg_F | Seg_G
CH_I	EQU		Seg_A | Seg_D | Seg_E
CH_J	EQU		Seg_A | Seg_C | Seg_D
CH_K	EQU		Seg_B | Seg_E | Seg_F | Seg_G
CH_L	EQU		Seg_D | Seg_E | Seg_F
CH_M	EQU		Seg_A | Seg_C | Seg_E | Seg_G
CH_N	EQU		Seg_C | Seg_E | Seg_G
CH_O	EQU		Seg_C | Seg_D | Seg_E | Seg_G
CH_P	EQU		Seg_A | Seg_B | Seg_E | Seg_F | Seg_G
CH_Q	EQU		Seg_A | Seg_B | Seg_C | Seg_F | Seg_G
CH_R	EQU		Seg_E | Seg_G
CH_S	EQU		Seg_A | Seg_C | Seg_D | Seg_F | Seg_G
CH_T	EQU		Seg_D | Seg_E | Seg_F | Seg_G
CH_U	EQU		Seg_B | Seg_C | Seg_D | Seg_E | Seg_F
CH_V	EQU		Seg_C | Seg_D | Seg_E
CH_W	EQU		Seg_B | Seg_D | Seg_F | Seg_G
CH_X	EQU		Seg_A | Seg_C | Seg_D | Seg_E
CH_Y	EQU		Seg_B | Seg_C | Seg_D | Seg_F | Seg_G
CH_Z	EQU		Seg_A | Seg_D | Seg_G
CH_Pt   EQU             Seg_H                                   ; Точка
CH_Tr	EQU		Seg_G            			; Тире
CH_Gr   EQU             Seg_A | Seg_B | Seg_F | Seg_G           ; Градус Цельсия  

  Т.к. мастер конфигураций обрабатывается препроцессором на этапе компиляции, он не занимает ни байта во флеш. К примеру после компиляции проекта только с этим файлом получилось:



  Это происходит потому, что мастер только назначает значения констант, самих констант он не определяет. Для того, чтобы можно было их определить в другом файле, необходимо экспортировать их символьные имена:

PUBLIC	CH_0, CH_1, CH_2, CH_3, CH_4, CH_5, CH_6, CH_7, CH_8, CH_9
PUBLIC	CH_A, CH_B, CH_C, CH_D, CH_E, CH_F, CH_G, CH_H, CH_I
PUBLIC	CH_J, CH_K, CH_L, CH_M, CH_N, CH_O, CH_P, CH_Q, CH_R
PUBLIC  CH_S, CH_T, CH_U, CH_V, CH_W, CH_X, CH_Y, CH_Z, CH_Tr, CH_Gr, CH_Pt

  Теперь в файле, в котором нужно выводить цифры, необходимо сначала импортировать нужные символьные имена, затем определить соответствующий контейнер для кодов символов:

NAME	CW_TEST
	
EXTRN NUMBER	(CH_0, CH_1, CH_2, CH_3, CH_4, CH_5, CH_6, CH_7, CH_8, CH_9)

CONST	SEGMENT	CODE	;  Таблица во Flash
	RSEG	CONST

TBL_DIGITS: 		; 0-9   
	DB	CH_0, CH_1, CH_2, CH_3, CH_4, CH_5, CH_6, CH_7, CH_8, CH_9  
		
END

Соответственно сразу для них и место выделится:



  • +2
  • 13 марта 2015, 23:16
  • anakost

Комментарии (5)

RSS свернуть / развернуть
молодец! разобрался!
0
#ifndef _DISP_7SEG_H_
#define _DISP_7SEG_H_
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include "conf.h"

#define DISP7S_SPORT0 PORTD
#define DISP7S_SDIR0 DDRD
#define DISP7S_SPORT1 PORTC
#define DISP7S_SDIR1 DDRC
#define DISP7S_DPORT0 PORTC
#define DISP7S_DDIR0 DDRC
#define DISP7S_DPORT1 PORTA
#define DISP7S_DDIR1 DDRA
#define DISP7S_DINV 0x1E00
//#define DISP7S_DINV 0xE080
#define DISP7S_SINV 0x0000
#define DISP7S_DMASK 0xFE80
#define DISP7S_SMASK 0x7CE0
#define DISP7S_DIGITS 8

#define DISP7S_DOT 0x80
#define DISP7S_UP 0x01
#define DISP7S_LO 0x08
#define DISP7S_MD 0x40
#define DISP7S_UR 0x02
#define DISP7S_LR 0x04
#define DISP7S_UL 0x20
#define DISP7S_LL 0x10
#define DISP7S_0 (DISP7S_UP | DISP7S_UR | DISP7S_LR | DISP7S_LO | DISP7S_LL | DISP7S_UL)
#define DISP7S_1 (DISP7S_UR | DISP7S_LR)
#define DISP7S_2 (DISP7S_UP | DISP7S_UR | DISP7S_MD | DISP7S_LL | DISP7S_LO)
#define DISP7S_3 (DISP7S_UP | DISP7S_MD | DISP7S_LO | DISP7S_UR | DISP7S_LR)
#define DISP7S_4 (DISP7S_UL | DISP7S_MD | DISP7S_UR | DISP7S_LR)
#define DISP7S_5 (DISP7S_UP | DISP7S_UL | DISP7S_MD | DISP7S_LR | DISP7S_LO)
#define DISP7S_6 (DISP7S_UP | DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_LL | DISP7S_LR)
#define DISP7S_7 (DISP7S_UP | DISP7S_UR | DISP7S_LR)
#define DISP7S_8 (DISP7S_UP | DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_UR | DISP7S_LR | DISP7S_LL)
#define DISP7S_9 (DISP7S_UP | DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_UR | DISP7S_LR)
#define DISP7S_A (DISP7S_UP | DISP7S_MD | DISP7S_UL | DISP7S_UR | DISP7S_LR | DISP7S_LL)
#define DISP7S_B (DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_LR | DISP7S_LL)
#define DISP7S_C (DISP7S_UP | DISP7S_LO | DISP7S_UL | DISP7S_LL)
#define DISP7S_D (DISP7S_MD | DISP7S_LO | DISP7S_UR | DISP7S_LR | DISP7S_LL)
#define DISP7S_E (DISP7S_UP | DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_LL)
#define DISP7S_F (DISP7S_UP | DISP7S_MD | DISP7S_UL | DISP7S_LL)
#define DISP7S_G (DISP7S_UP | DISP7S_LO | DISP7S_UL | DISP7S_LL | DISP7S_LR)
#define DISP7S_H (DISP7S_MD | DISP7S_UL | DISP7S_UR | DISP7S_LR | DISP7S_LL)
#define DISP7S_I (DISP7S_UL | DISP7S_LL)
#define DISP7S_J (DISP7S_UR | DISP7S_LR | DISP7S_LO)
#define DISP7S_L (DISP7S_UL | DISP7S_LL | DISP7S_LO)
#define DISP7S_O DISP7S_0
#define DISP7S_P (DISP7S_UP | DISP7S_MD | DISP7S_UL | DISP7S_UR | DISP7S_LL)
#define DISP7S_S DISP7S_5
#define DISP7S_T (DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_LL)
#define DISP7S_U (DISP7S_UR | DISP7S_LR | DISP7S_LO | DISP7S_LL | DISP7S_UL)
#define DISP7S_Y (DISP7S_MD | DISP7S_LO | DISP7S_UL | DISP7S_UR | DISP7S_LR)
#define DISP7S_Z DISP7S_2
#define DISP7S_DIV (DISP7S_UP | DISP7S_MD | DISP7S_LO)
#define DISP7S_LP (DISP7S_UP | DISP7S_LO | DISP7S_UL | DISP7S_LL)
#define DISP7S_RP (DISP7S_UP | DISP7S_LO | DISP7S_UR | DISP7S_LR)
#define DISP7S_MINUS (DISP7S_MD)
#define DISP7S_SNAKE_0 (DISP7S_UL | DISP7S_UP)
#define DISP7S_SNAKE_1 (DISP7S_UP | DISP7S_UR)
#define DISP7S_SNAKE_2 (DISP7S_UR | DISP7S_MD)
#define DISP7S_SNAKE_3 (DISP7S_MD | DISP7S_LL)
#define DISP7S_SNAKE_4 (DISP7S_LL | DISP7S_LO)
#define DISP7S_SNAKE_5 (DISP7S_LO | DISP7S_LR)
#define DISP7S_SNAKE_6 (DISP7S_LR | DISP7S_MD)
#define DISP7S_SNAKE_7 (DISP7S_MD | DISP7S_UL)

extern void disp_7seg_init();
extern void disp_7seg_digit(char n);
extern void disp_7seg_segment(char s, char n);
extern void disp_7seg_off();
extern void disp_7seg_scan();
extern void disp_7seg_str(char *str, char i, char n);

extern volatile char disp_7seg_bfr[DISP7S_DIGITS];
extern volatile char disp_7seg_cur;

#endif
0

#include <avr/pgmspace.h>
#include <string.h>
#include "timer.h"
#include "uart.h"
#include "disp_7seg.h"
#include "global.h"

volatile char disp_7seg_bfr[DISP7S_DIGITS];

volatile char disp_7seg_cur;

const char disp_7seg_ct[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, // !"#
0x00, 0x00, 0x00, 0x00, //$%&'
DISP7S_LP, DISP7S_RP, 0x00, 0x00, //()*+
DISP7S_DOT, DISP7S_MINUS, DISP7S_DOT, DISP7S_DIV, //,-./
DISP7S_0, DISP7S_1, DISP7S_2, DISP7S_3, //0123
DISP7S_4, DISP7S_5, DISP7S_6, DISP7S_7, //4567
DISP7S_8, DISP7S_9, DISP7S_DOT, DISP7S_DOT, //89:;
0x00, 0x00, 0x00, 0x00, //<=>?
0x00, DISP7S_A, DISP7S_B, DISP7S_C, //@ABC
DISP7S_D, DISP7S_E, DISP7S_F, DISP7S_G, //DEFG
DISP7S_H, DISP7S_I, DISP7S_J, DISP7S_H, //HIJK
DISP7S_L, 0x00, 0x00, DISP7S_O, //LMNO
DISP7S_P, 0x00, 0x00, DISP7S_S, //PQRS
DISP7S_T, DISP7S_U, 0x00, 0x00, //TUVW
0x00, DISP7S_Y, DISP7S_Z, DISP7S_LP, //XYZ[
0x00, DISP7S_RP, DISP7S_UP, DISP7S_LO, //\]^_
DISP7S_UL, DISP7S_A, DISP7S_B, DISP7S_C, //`abc
DISP7S_D, DISP7S_E, DISP7S_F, DISP7S_G, //DEFG
DISP7S_H, DISP7S_I, DISP7S_J, 0x00, //HIJK
DISP7S_L, 0x00, 0x00, DISP7S_O, //LMNO
DISP7S_P, 0x00, 0x00, DISP7S_S, //PQRS
DISP7S_T, DISP7S_U, 0x00, 0x00, //TUVW
0x00, DISP7S_Y, DISP7S_Z, DISP7S_LP, //XYZ[
DISP7S_I, DISP7S_RP, DISP7S_MINUS, DISP7S_DOT //|}~.
};

#define DISP7S_D_0 0x2000
#define DISP7S_D_1 0x4000
#define DISP7S_D_2 0x8000
#define DISP7S_D_3 0x0080
#define DISP7S_D_4 0x0200
#define DISP7S_D_5 0x0400
#define DISP7S_D_6 0x0800
#define DISP7S_D_7 0x1000

const int disp_7seg_d[DISP7S_DIGITS] PROGMEM = {
	(DISP7S_D_0 ^ DISP7S_DINV), (DISP7S_D_1 ^ DISP7S_DINV),
	(DISP7S_D_2 ^ DISP7S_DINV), (DISP7S_D_3 ^ DISP7S_DINV),
	(DISP7S_D_4 ^ DISP7S_DINV), (DISP7S_D_5 ^ DISP7S_DINV),
	(DISP7S_D_6 ^ DISP7S_DINV), (DISP7S_D_7 ^ DISP7S_DINV)
};

const char disp_7seg_i[DISP7S_DIGITS] = {
	0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF
};

const int disp_7seg_s[] = {
	0x0020 ^ DISP7S_SINV, 0x0040 ^ DISP7S_SINV,
	0x0080 ^ DISP7S_SINV, 0x0400 ^ DISP7S_SINV,
	0x0800 ^ DISP7S_SINV, 0x1000 ^ DISP7S_SINV,
	0x2000 ^ DISP7S_SINV, 0x4000 ^ DISP7S_SINV
};

void disp_7seg_init()
{
	disp_7seg_cur = 0;
	memset(disp_7seg_bfr, 0, DISP7S_DIGITS);
	DISP7S_SDIR0 |= (DISP7S_SMASK & 0xFF);
	DISP7S_DDIR0 |= (DISP7S_DMASK & 0xFF);
	DISP7S_SDIR1 |= (DISP7S_SMASK >> 8);
	DISP7S_DDIR1 |= (DISP7S_DMASK >> 8);
}

void disp_7seg_shift_left()
{
	memmove(disp_7seg_bfr, disp_7seg_bfr + 1, DISP7S_DIGITS);
}

void disp_7seg_shift_right()
{
	memmove(disp_7seg_bfr + 1, disp_7seg_bfr, DISP7S_DIGITS);
}

void disp_7seg_digit(char n)
{
	DISP7S_DPORT0 = (DISP7S_DPORT0 & (~( DISP7S_DMASK & 0xFF) ) ) | pgm_read_byte( (char*)(&disp_7seg_d[n]) + 0);
	DISP7S_DPORT1 = (DISP7S_DPORT1 & (~( DISP7S_DMASK >> 8  ) ) ) | pgm_read_byte( (char*)(&disp_7seg_d[n]) + 1);
}

void disp_7seg_off()
{
	DISP7S_DPORT0 = ( DISP7S_DPORT0 & ( (~DISP7S_DMASK) & 0xFF) ) | ( ( (~(DISP7S_DINV ^ DISP7S_DMASK)) & DISP7S_DMASK) & 0xFF );
	DISP7S_DPORT1 = ( DISP7S_DPORT1 & ( (~DISP7S_DMASK) >>   8) ) | ( ( (~(DISP7S_DINV ^ DISP7S_DMASK)) & DISP7S_DMASK) >>   8 );
}

void disp_7seg_segment(char s, char n)
{
	int d = 0;
	s ^= disp_7seg_i[n];
	if( s & 0x01 ) d |= disp_7seg_s[0];
	if( s & 0x02 ) d |= disp_7seg_s[1];
	if( s & 0x04 ) d |= disp_7seg_s[2];
	if( s & 0x08 ) d |= disp_7seg_s[3];
	if( s & 0x10 ) d |= disp_7seg_s[4];
	if( s & 0x20 ) d |= disp_7seg_s[5];
	if( s & 0x40 ) d |= disp_7seg_s[6];
	if( s & 0x80 ) d |= disp_7seg_s[7];
	DISP7S_SPORT0 = (DISP7S_SPORT0 & (~( DISP7S_SMASK & 0xFF) ) ) | (d & 0xFF);
	DISP7S_SPORT1 = (DISP7S_SPORT1 & (~( DISP7S_SMASK >>   8) ) ) | (d >>   8);
}

void disp_7seg_scan()
{
	char n = disp_7seg_cur;
	disp_7seg_off();
	disp_7seg_segment(disp_7seg_bfr[n], n);
	disp_7seg_digit(n);
	n ++;
	disp_7seg_cur = (n >= DISP7S_DIGITS)? 0 : n;
}

void disp_7seg_str(char *str, char i, char n)
{
	char *bfr = disp_7seg_bfr + i;
	unsigned char c;
	if( n == 0 ) n = -1;
	while(n)
	{
		c = *(str++);
		if( c == 0 ) break;
		c = pgm_read_byte( &disp_7seg_ct[ (c - 0x20) & 0x7F ] );
		if( c == DISP7S_DOT )
		{
			if( i == 0 )
			{
				*bfr = DISP7S_DOT;
				i++;
			}
			else *(bfr-1) |= DISP7S_DOT;
		}
		else
		{
			*bfr = c;
			bfr++;
			i++;
			if(i > DISP7S_DIGITS) break;
		}
		n--;
	}
}
0
и где-нибудь в прерываниях:


	if(disp_seg_time == 0) disp_7seg_scan();
	if(disp_seg_time == disp_seg_lvl) disp_7seg_off();
	disp_seg_time ++;
	disp_seg_time &= 0x7;


юзать можно так:

disp_7seg_str("F.U.C.K.", 0, 8); //если с точками
disp_7seg_str("FUCK", 0, 8); //если без точек


может ОПу пригодится.
0
ОП!
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.