- как оно вообще, сравнить вместо деления, по скорости? всё равно в той переменной будут только цифры аля 400, 70000, 200000 и т д, то есть одна полезная цифра плюс куча нулей, которые надо делить только ради того чтобы понять что это допустим 2 раза по 100000.
Voodoo Doll, почему форумчане не кинулись править ваш код? Так это из-за уважения. Но по факту вы нарушили все написанные и ненаписанные правила при написании кода. Так что подымайте литературу и учите.
Вот про это я и говорю. Язык Си создавался как язык высокого уровня, который может работать на низком уровне. Что такое язык высокого уровня? Это любой программист средней квалификации глядя на код, сразу поймет какое железо и софт используется в программе. Но зачем писать на Си словно это ассемблер.
sadman41 пишет:
О семисегментном LED.
Семисегментные LED бывают разные одиночные, двойные и так далее.
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Ассемблер полезно представлять себе хотя бы затем, чтобы проверить, а чего же там намудрил компилятор. Потому как бывают варианты.
Ну и еще полезно представлять, во что именно выльется та или иная строка на Си. Потому как одна строка превращается в 2-3 оператора, которые выполняются 2-3 такта, а другая - ведет к вызову функции, которая может выполняться не одну тысячу тактов.
Ну да. Однако знать ассемблер, что бы посмотреть, что там намудрил компилятор не обязательно. Достаточно знать ассемблерные комаманды процессора - это необходимый минимум.
Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.
Для себя вы можете писать как угодно. Только критерии нужно установить - быстро, компактно, хитронакручено и т.д. Как правило, в большинстве случаев, это всё лишнее. Иначе, пишите на ассемблере.
Если выставляете на оценку - должны понимать что читают люди. А значит лаконично и понятно (а не хитрозакручено), правильно оформлено и переносимо.
Критикую
заглушка
С заглавной буквы нужно было!
001
#define INT_UPD_DIG (500)
002
003
byte
digits[13]={B01000000,B01111001,B00100100,B00110000,B00011001,B00010010,B00000010,B01111000,B00000000,B00010000,
004
// 0 1 2 3 4 5 6 7 8 9
005
B01111111,B00001110,B01000110};
006
// blank freq cap
007
008
byte
n=0;
009
unsigned
long
last_dig_upd=millis(),
010
read_data, read_div, read_mod;
011
byte
disp_data[12]={0,0,0,0,0,0,0,0,0,0,0,0};
// 0..6: physical display shadow, 7..11: divide shadow
012
013
void
setup
(){
014
DDRD|=B11011111;
015
DDRB|=B00000111;
016
DDRC|=B00111000;
017
PORTD|=B11000011;
018
PORTB|=B00000111;
019
}
020
021
void
loop
(){
022
byte
i=6,j=0;
023
bool
found_nonzero=
false
;
024
025
while
(i<11){
026
divmod10(read_data, read_div, read_mod);
027
fill_disp_data(i);
028
read_data=read_mod;
029
i++;
030
}
031
fill_disp_data(11);
032
033
for
(i=11;i>=6;i--){
034
disp_data[j]=disp_data[i];
035
if
(disp_data[i]>0) found_nonzero=
true
;
036
if
(!found_nonzero) disp_data[j]=10;
// write blank to kill leading zero
037
j++;
038
}
039
040
proc_disp();
041
}
042
043
void
divmod10(uint32_t
in
, uint32_t &div, uint32_t &mod){
044
uint32_t x=(
in
>>1);
045
uint32_t q=x;
046
q= (q>>8) + x;
047
q= (q>>8) + x;
048
q= (q>>8) + x;
049
q= (q>>8) + x + 1;
050
x= q;
051
q= (q>>1) + x;
052
q= (q>>3) + x;
053
q= (q>>1) + x;
054
div = (q >> 3);
055
mod =
in
- (((div << 2) + div) << 1);
056
}
057
058
void
proc_disp(){
059
byte
n_dig=0;
060
switch
(n_dig){
061
case
0: PORTC|=B00110000; PORTD|=B00011100; PORTC&=B11110111;
break
;
// whether common anode 1 is on
062
case
1: PORTC|=B00011000; PORTD|=B00011100; PORTC&=B11011111;
break
;
// ca 2
063
case
2: PORTC|=B00101000; PORTD|=B00011100; PORTC&=B11101111;
break
;
// ca 3
064
case
3: PORTC|=B00111000; PORTD|=B00001100; PORTD&=B11101111;
break
;
// ca 4
065
case
4: PORTC|=B00111000; PORTD|=B00011000; PORTD&=B11111011;
break
;
// ca 5
066
case
5: PORTC|=B00111000; PORTD|=B00010100; PORTD&=B11110111;
break
;
// ca 6
067
}
068
n_dig++;
069
if
(n_dig>5) n_dig=0;
070
071
if
(millis()-last_dig_upd>=INT_UPD_DIG){
072
if
(digits[n]&B00000001){ PORTD|=B00000001; }
else
{ PORTD&=B11111110; }
// whether G is off
073
if
(digits[n]&B00000010){ PORTD|=B00000010; }
else
{ PORTD&=B11111101; }
// F
074
if
(digits[n]&B00000100){ PORTB|=B00000001; }
else
{ PORTB&=B11111110; }
// E
075
if
(digits[n]&B00001000){ PORTD|=B01000000; }
else
{ PORTD&=B10111111; }
// D
076
if
(digits[n]&B00010000){ PORTD|=B10000000; }
else
{ PORTD&=B01111111; }
// C
077
if
(digits[n]&B00100000){ PORTB|=B00000100; }
else
{ PORTB&=B11111011; }
// B
078
if
(digits[n]&B01000000){ PORTB|=B00000010; }
else
{ PORTB&=B11111101; }
// A
079
n++;
080
if
(n>12) n=0;
081
last_dig_upd=millis();
082
}
083
}
084
085
void
fill_disp_data(
byte
pos){
086
switch
(pos){
087
case
6:
if
(read_div==0) disp_data[pos]=0;
088
if
(read_div==100000) disp_data[pos]=1;
089
if
(read_div==200000) disp_data[pos]=2;
090
if
(read_div==300000) disp_data[pos]=3;
091
if
(read_div==400000) disp_data[pos]=4;
092
if
(read_div==500000) disp_data[pos]=5;
093
if
(read_div==600000) disp_data[pos]=6;
094
if
(read_div==700000) disp_data[pos]=7;
095
if
(read_div==800000) disp_data[pos]=8;
096
if
(read_div==900000) disp_data[pos]=9;
break
;
097
case
7:
if
(read_div==0) disp_data[pos]=0;
098
if
(read_div==10000) disp_data[pos]=1;
099
if
(read_div==20000) disp_data[pos]=2;
100
if
(read_div==30000) disp_data[pos]=3;
101
if
(read_div==40000) disp_data[pos]=4;
102
if
(read_div==50000) disp_data[pos]=5;
103
if
(read_div==60000) disp_data[pos]=6;
104
if
(read_div==70000) disp_data[pos]=7;
105
if
(read_div==80000) disp_data[pos]=8;
106
if
(read_div==90000) disp_data[pos]=9;
break
;
107
case
8:
if
(read_div==0) disp_data[pos]=0;
108
if
(read_div==1000) disp_data[pos]=1;
109
if
(read_div==2000) disp_data[pos]=2;
110
if
(read_div==3000) disp_data[pos]=3;
111
if
(read_div==4000) disp_data[pos]=4;
112
if
(read_div==5000) disp_data[pos]=5;
113
if
(read_div==6000) disp_data[pos]=6;
114
if
(read_div==7000) disp_data[pos]=7;
115
if
(read_div==8000) disp_data[pos]=8;
116
if
(read_div==9000) disp_data[pos]=9;
break
;
117
case
9:
if
(read_div==0) disp_data[pos]=0;
118
if
(read_div==100) disp_data[pos]=1;
119
if
(read_div==200) disp_data[pos]=2;
120
if
(read_div==300) disp_data[pos]=3;
121
if
(read_div==400) disp_data[pos]=4;
122
if
(read_div==500) disp_data[pos]=5;
123
if
(read_div==600) disp_data[pos]=6;
124
if
(read_div==700) disp_data[pos]=7;
125
if
(read_div==800) disp_data[pos]=8;
126
if
(read_div==900) disp_data[pos]=9;
break
;
127
case
10:
if
(read_div==0) disp_data[pos]=0;
128
if
(read_div==10) disp_data[pos]=1;
129
if
(read_div==20) disp_data[pos]=2;
130
if
(read_div==30) disp_data[pos]=3;
131
if
(read_div==40) disp_data[pos]=4;
132
if
(read_div==50) disp_data[pos]=5;
133
if
(read_div==60) disp_data[pos]=6;
134
if
(read_div==70) disp_data[pos]=7;
135
if
(read_div==80) disp_data[pos]=8;
136
if
(read_div==90) disp_data[pos]=9;
break
;
137
case
11: disp_data[pos]=read_mod;
break
;
138
}
139
}
гавно?
Вопросы:
- быстрее ли писать конкретный в массиве, чем динамически? т. о.
1
case
9:
/*......*/
2
if
(read_div==400) disp_data[9]=4;
вместо
1
case
9:
/*......*/
2
if
(read_div==400) disp_data[pos]=4;
- как оно вообще, сравнить вместо деления, по скорости? всё равно в той переменной будут только цифры аля 400, 70000, 200000 и т д, то есть одна полезная цифра плюс куча нулей, которые надо делить только ради того чтобы понять что это допустим 2 раза по 100000.
по схеме: kingbright ba-56 два штуки, общие кинуты на pnp-транзисторы (т. е нулём включаются и аноды и катоды)
upd: на процедуру proc_disp пока можно не обращать внимания, там тестовая версия из голого loop() (тикающие 0-9, blank, F, C цифры)
фак, только что дошло что я считаю деление не с той стороны числа. ладно пофиг, перепишу и выложу, думаю ясен принцип? вопрос тот же.
Там не то что принцип, там вообще ниуя не ясно.
Особенно непонятно, зачем в сетапе так порты инициализировать.
01
#define INT_UPD_DIG (500)
02
03
byte
digits[13]={B01000000,B01111001,B00100100,B00110000,B00011001,B00010010,B00000010,B01111000,B00000000,B00010000,
04
// 0 1 2 3 4 5 6 7 8 9
05
B01111111,B00001110,B01000110};
06
// blank freq cap
07
08
unsigned
long
read_data, read_div, read_mod;
09
byte
disp_data[6]={0,0,0,0,0,0};
// display shadow
10
11
void
setup
(){
12
DDRD|=B11011111;
13
DDRB|=B00000111;
14
DDRC|=B00111000;
15
PORTD|=B11000011;
16
PORTB|=B00000111;
17
}
18
19
void
loop
(){
20
byte
i;
21
bool
found_nonzero=
false
;
22
23
read_data=228420;
//debug
24
25
for
(i=5;i>=1;i--){
26
divmod10(read_data, read_div, read_mod);
27
disp_data[i]=read_mod;
28
read_data=read_div;
29
}
30
disp_data[0]=read_data;
31
32
for
(i=0;i<=5;i++){
33
if
(disp_data[i]>0) found_nonzero=
true
;
34
if
(!found_nonzero) disp_data[i]=10;
// write blank to kill leading zero
35
}
36
37
proc_disp();
38
}
39
40
void
divmod10(uint32_t
in
, uint32_t &div, uint32_t &mod){
41
uint32_t x=(
in
>>1);
42
uint32_t q=x;
43
q= (q>>8) + x;
44
q= (q>>8) + x;
45
q= (q>>8) + x;
46
q= (q>>8) + x + 1;
47
x= q;
48
q= (q>>1) + x;
49
q= (q>>3) + x;
50
q= (q>>1) + x;
51
div = (q >> 3);
52
mod =
in
- (((div << 2) + div) << 1);
53
}
54
55
void
proc_disp(){
56
byte
n_dig=0;
57
for
(n_dig=0;n_dig<=5;n_dig++){
58
switch
(n_dig){
59
case
0: PORTC|=B00110000; PORTD|=B00011100; PORTC&=B11110111;
break
;
// whether common anode 1 is on
60
case
1: PORTC|=B00011000; PORTD|=B00011100; PORTC&=B11011111;
break
;
// ca 2
61
case
2: PORTC|=B00101000; PORTD|=B00011100; PORTC&=B11101111;
break
;
// ca 3
62
case
3: PORTC|=B00111000; PORTD|=B00001100; PORTD&=B11101111;
break
;
// ca 4
63
case
4: PORTC|=B00111000; PORTD|=B00011000; PORTD&=B11111011;
break
;
// ca 5
64
case
5: PORTC|=B00111000; PORTD|=B00010100; PORTD&=B11110111;
break
;
// ca 6
65
}
66
if
(disp_data[n_dig]&B00000001){ PORTD|=B00000001; }
else
{ PORTD&=B11111110; }
// whether G is off
67
if
(disp_data[n_dig]&B00000010){ PORTD|=B00000010; }
else
{ PORTD&=B11111101; }
// F
68
if
(disp_data[n_dig]&B00000100){ PORTB|=B00000001; }
else
{ PORTB&=B11111110; }
// E
69
if
(disp_data[n_dig]&B00001000){ PORTD|=B01000000; }
else
{ PORTD&=B10111111; }
// D
70
if
(disp_data[n_dig]&B00010000){ PORTD|=B10000000; }
else
{ PORTD&=B01111111; }
// C
71
if
(disp_data[n_dig]&B00100000){ PORTB|=B00000100; }
else
{ PORTB&=B11111011; }
// B
72
if
(disp_data[n_dig]&B01000000){ PORTB|=B00000010; }
else
{ PORTB&=B11111101; }
// A
73
}
74
}
доделанная версия
Kakmyc, так быстрее
Вопросы:
- быстрее ли писать конкретный в массиве, чем динамически? т. о.
1
case
9:
/*......*/
2
if
(read_div==400) disp_data[9]=4;
вместо
1
case
9:
/*......*/
2
if
(read_div==400) disp_data[pos]=4;
Константа - она завсегда быстрее и предсказуемей в работе, но сложнее в саппорте.
Деление потенциально тяжелее сравнения, если только деление при оптимизации на битшифт не заменяется.
Быдлокод. DDR-ы, PORT-ы, всякие B000000 заменяешь смысловыми значениями. Определяешь сегменты, общие, начертание отображаемых символов и т.д. Пример индикации.
01
uint8_t segment[COM_MAX];
02
bool
dot;
03
04
05
void
ledExe() {
06
static
uint8_t com;
07
08
segment_off();
//выключим всё
09
com_off();
10
switch
(com) {
//включим один общий
11
case
0: com1_on();
break
;
12
case
1: com2_on();
break
;
13
case
2: com3_on();
break
;
14
}
15
segment_on(segment[com]);
//включим сегменты
16
if
(++com >= COM_MAX)
//следующая позиция
17
com = 0;
18
}
Voodoo Doll, почему форумчане не кинулись править ваш код? Так это из-за уважения. Но по факту вы нарушили все написанные и ненаписанные правила при написании кода. Так что подымайте литературу и учите.
Мне вот не понятно все же, почему ТС твердо уверен , что все поняли о каком дисплее ("экране") идёт речь ?
О семисегментном LED.
Вот про это я и говорю. Язык Си создавался как язык высокого уровня, который может работать на низком уровне. Что такое язык высокого уровня? Это любой программист средней квалификации глядя на код, сразу поймет какое железо и софт используется в программе. Но зачем писать на Си словно это ассемблер.
Семисегментные LED бывают разные одиночные, двойные и так далее.
Ппц сразу ясно стало какой экран.
Теперь осталось узнать о каком типе индикации идёт речь
Бл. Написано же: kingbright ba-56.
И этот сегментник не мой, не надо меня пригружать.
Такого определения ещё не видел! Буду знать.
Это любой программист средней квалификации глядя на код, сразу поймет какое железо...
Очень смешно ляпнул про кросплатформенный язык.
Но код таки гамно.
Чего бы не написать стр.66 и далее типа
1
byte
Seg[]={B00000001,B00000010,B00000001,B01000000,B10000000,B00000100,B00000010};
// эти константы и именовать не грешно бы
2
3
..
4
5
for
(
byte
a=digits[n_dig], i=0;i<7;i--,a>>=1)
6
{
7
if
(a&1){ PORTD|=Seg[i]; }
else
{ PORTD&=~Seg[i]; }
8
}
а то что в свиче fill_disp_data - адское адище.
Зачем вообще нужно это недоразумение , если все намного проще ?
Люди, а ассемблер сложно учить? Может быть я реально зря на c (даж не c++) пишу...
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Ассемблер полезно представлять себе хотя бы затем, чтобы проверить, а чего же там намудрил компилятор. Потому как бывают варианты.
Ну и еще полезно представлять, во что именно выльется та или иная строка на Си. Потому как одна строка превращается в 2-3 оператора, которые выполняются 2-3 такта, а другая - ведет к вызову функции, которая может выполняться не одну тысячу тактов.
Ну да. Однако знать ассемблер, что бы посмотреть, что там намудрил компилятор не обязательно. Достаточно знать ассемблерные комаманды процессора - это необходимый минимум.
Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.
Для себя вы можете писать как угодно. Только критерии нужно установить - быстро, компактно, хитронакручено и т.д. Как правило, в большинстве случаев, это всё лишнее. Иначе, пишите на ассемблере.
Если выставляете на оценку - должны понимать что читают люди. А значит лаконично и понятно (а не хитрозакручено), правильно оформлено и переносимо.