#define INT_UPD_DIG (500)
byte digits[13]={B01000000,B01111001,B00100100,B00110000,B00011001,B00010010,B00000010,B01111000,B00000000,B00010000,
// 0 1 2 3 4 5 6 7 8 9
B01111111,B00001110,B01000110};
// blank freq cap
byte n=0;
unsigned long last_dig_upd=millis(),
read_data, read_div, read_mod;
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
void setup(){
DDRD|=B11011111;
DDRB|=B00000111;
DDRC|=B00111000;
PORTD|=B11000011;
PORTB|=B00000111;
}
void loop(){
byte i=6,j=0;
bool found_nonzero=false;
while(i<11){
divmod10(read_data, read_div, read_mod);
fill_disp_data(i);
read_data=read_mod;
i++;
}
fill_disp_data(11);
for(i=11;i>=6;i--){
disp_data[j]=disp_data[i];
if(disp_data[i]>0) found_nonzero=true;
if(!found_nonzero) disp_data[j]=10; // write blank to kill leading zero
j++;
}
proc_disp();
}
void divmod10(uint32_t in, uint32_t &div, uint32_t &mod){
uint32_t x=(in>>1);
uint32_t q=x;
q= (q>>8) + x;
q= (q>>8) + x;
q= (q>>8) + x;
q= (q>>8) + x + 1;
x= q;
q= (q>>1) + x;
q= (q>>3) + x;
q= (q>>1) + x;
div = (q >> 3);
mod = in - (((div << 2) + div) << 1);
}
void proc_disp(){
byte n_dig=0;
switch(n_dig){
case 0: PORTC|=B00110000; PORTD|=B00011100; PORTC&=B11110111; break; // whether common anode 1 is on
case 1: PORTC|=B00011000; PORTD|=B00011100; PORTC&=B11011111; break; // ca 2
case 2: PORTC|=B00101000; PORTD|=B00011100; PORTC&=B11101111; break; // ca 3
case 3: PORTC|=B00111000; PORTD|=B00001100; PORTD&=B11101111; break; // ca 4
case 4: PORTC|=B00111000; PORTD|=B00011000; PORTD&=B11111011; break; // ca 5
case 5: PORTC|=B00111000; PORTD|=B00010100; PORTD&=B11110111; break; // ca 6
}
n_dig++;
if(n_dig>5) n_dig=0;
if(millis()-last_dig_upd>=INT_UPD_DIG){
if(digits[n]&B00000001){ PORTD|=B00000001; }else{ PORTD&=B11111110; } // whether G is off
if(digits[n]&B00000010){ PORTD|=B00000010; }else{ PORTD&=B11111101; } // F
if(digits[n]&B00000100){ PORTB|=B00000001; }else{ PORTB&=B11111110; } // E
if(digits[n]&B00001000){ PORTD|=B01000000; }else{ PORTD&=B10111111; } // D
if(digits[n]&B00010000){ PORTD|=B10000000; }else{ PORTD&=B01111111; } // C
if(digits[n]&B00100000){ PORTB|=B00000100; }else{ PORTB&=B11111011; } // B
if(digits[n]&B01000000){ PORTB|=B00000010; }else{ PORTB&=B11111101; } // A
n++;
if(n>12) n=0;
last_dig_upd=millis();
}
}
void fill_disp_data(byte pos){
switch(pos){
case 6: if(read_div==0) disp_data[pos]=0;
if(read_div==100000) disp_data[pos]=1;
if(read_div==200000) disp_data[pos]=2;
if(read_div==300000) disp_data[pos]=3;
if(read_div==400000) disp_data[pos]=4;
if(read_div==500000) disp_data[pos]=5;
if(read_div==600000) disp_data[pos]=6;
if(read_div==700000) disp_data[pos]=7;
if(read_div==800000) disp_data[pos]=8;
if(read_div==900000) disp_data[pos]=9; break;
case 7: if(read_div==0) disp_data[pos]=0;
if(read_div==10000) disp_data[pos]=1;
if(read_div==20000) disp_data[pos]=2;
if(read_div==30000) disp_data[pos]=3;
if(read_div==40000) disp_data[pos]=4;
if(read_div==50000) disp_data[pos]=5;
if(read_div==60000) disp_data[pos]=6;
if(read_div==70000) disp_data[pos]=7;
if(read_div==80000) disp_data[pos]=8;
if(read_div==90000) disp_data[pos]=9; break;
case 8: if(read_div==0) disp_data[pos]=0;
if(read_div==1000) disp_data[pos]=1;
if(read_div==2000) disp_data[pos]=2;
if(read_div==3000) disp_data[pos]=3;
if(read_div==4000) disp_data[pos]=4;
if(read_div==5000) disp_data[pos]=5;
if(read_div==6000) disp_data[pos]=6;
if(read_div==7000) disp_data[pos]=7;
if(read_div==8000) disp_data[pos]=8;
if(read_div==9000) disp_data[pos]=9; break;
case 9: if(read_div==0) disp_data[pos]=0;
if(read_div==100) disp_data[pos]=1;
if(read_div==200) disp_data[pos]=2;
if(read_div==300) disp_data[pos]=3;
if(read_div==400) disp_data[pos]=4;
if(read_div==500) disp_data[pos]=5;
if(read_div==600) disp_data[pos]=6;
if(read_div==700) disp_data[pos]=7;
if(read_div==800) disp_data[pos]=8;
if(read_div==900) disp_data[pos]=9; break;
case 10: if(read_div==0) disp_data[pos]=0;
if(read_div==10) disp_data[pos]=1;
if(read_div==20) disp_data[pos]=2;
if(read_div==30) disp_data[pos]=3;
if(read_div==40) disp_data[pos]=4;
if(read_div==50) disp_data[pos]=5;
if(read_div==60) disp_data[pos]=6;
if(read_div==70) disp_data[pos]=7;
if(read_div==80) disp_data[pos]=8;
if(read_div==90) disp_data[pos]=9; break;
case 11: disp_data[pos]=read_mod; break;
}
}
гавно?
Вопросы:
- быстрее ли писать конкретный в массиве, чем динамически? т. о.
case 9: /*......*/
if(read_div==400) disp_data[9]=4;
вместо
case 9: /*......*/
if(read_div==400) disp_data[pos]=4;
- как оно вообще, сравнить вместо деления, по скорости? всё равно в той переменной будут только цифры аля 400, 70000, 200000 и т д, то есть одна полезная цифра плюс куча нулей, которые надо делить только ради того чтобы понять что это допустим 2 раза по 100000.
Voodoo Doll, почему форумчане не кинулись править ваш код? Так это из-за уважения. Но по факту вы нарушили все написанные и ненаписанные правила при написании кода. Так что подымайте литературу и учите.
Вот про это я и говорю. Язык Си создавался как язык высокого уровня, который может работать на низком уровне. Что такое язык высокого уровня? Это любой программист средней квалификации глядя на код, сразу поймет какое железо и софт используется в программе. Но зачем писать на Си словно это ассемблер.
sadman41 пишет:
О семисегментном LED.
Семисегментные LED бывают разные одиночные, двойные и так далее.
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Ассемблер полезно представлять себе хотя бы затем, чтобы проверить, а чего же там намудрил компилятор. Потому как бывают варианты.
Ну и еще полезно представлять, во что именно выльется та или иная строка на Си. Потому как одна строка превращается в 2-3 оператора, которые выполняются 2-3 такта, а другая - ведет к вызову функции, которая может выполняться не одну тысячу тактов.
Ну да. Однако знать ассемблер, что бы посмотреть, что там намудрил компилятор не обязательно. Достаточно знать ассемблерные комаманды процессора - это необходимый минимум.
Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.
Для себя вы можете писать как угодно. Только критерии нужно установить - быстро, компактно, хитронакручено и т.д. Как правило, в большинстве случаев, это всё лишнее. Иначе, пишите на ассемблере.
Если выставляете на оценку - должны понимать что читают люди. А значит лаконично и понятно (а не хитрозакручено), правильно оформлено и переносимо.
Критикую
заглушка
С заглавной буквы нужно было!
гавно?
Вопросы:
- быстрее ли писать конкретный в массиве, чем динамически? т. о.
вместо
- как оно вообще, сравнить вместо деления, по скорости? всё равно в той переменной будут только цифры аля 400, 70000, 200000 и т д, то есть одна полезная цифра плюс куча нулей, которые надо делить только ради того чтобы понять что это допустим 2 раза по 100000.
по схеме: kingbright ba-56 два штуки, общие кинуты на pnp-транзисторы (т. е нулём включаются и аноды и катоды)
upd: на процедуру proc_disp пока можно не обращать внимания, там тестовая версия из голого loop() (тикающие 0-9, blank, F, C цифры)
фак, только что дошло что я считаю деление не с той стороны числа. ладно пофиг, перепишу и выложу, думаю ясен принцип? вопрос тот же.
Там не то что принцип, там вообще ниуя не ясно.
Особенно непонятно, зачем в сетапе так порты инициализировать.
доделанная версия
Kakmyc, так быстрее
Вопросы:
- быстрее ли писать конкретный в массиве, чем динамически? т. о.
вместо
Константа - она завсегда быстрее и предсказуемей в работе, но сложнее в саппорте.
Деление потенциально тяжелее сравнения, если только деление при оптимизации на битшифт не заменяется.
Быдлокод. DDR-ы, PORT-ы, всякие B000000 заменяешь смысловыми значениями. Определяешь сегменты, общие, начертание отображаемых символов и т.д. Пример индикации.
Voodoo Doll, почему форумчане не кинулись править ваш код? Так это из-за уважения. Но по факту вы нарушили все написанные и ненаписанные правила при написании кода. Так что подымайте литературу и учите.
Мне вот не понятно все же, почему ТС твердо уверен , что все поняли о каком дисплее ("экране") идёт речь ?
О семисегментном LED.
Вот про это я и говорю. Язык Си создавался как язык высокого уровня, который может работать на низком уровне. Что такое язык высокого уровня? Это любой программист средней квалификации глядя на код, сразу поймет какое железо и софт используется в программе. Но зачем писать на Си словно это ассемблер.
Семисегментные LED бывают разные одиночные, двойные и так далее.
Ппц сразу ясно стало какой экран.
Теперь осталось узнать о каком типе индикации идёт речь
Бл. Написано же: kingbright ba-56.
И этот сегментник не мой, не надо меня пригружать.
Такого определения ещё не видел! Буду знать.
Это любой программист средней квалификации глядя на код, сразу поймет какое железо...
Очень смешно ляпнул про кросплатформенный язык.
Но код таки гамно.
Чего бы не написать стр.66 и далее типа
а то что в свиче fill_disp_data - адское адище.
Зачем вообще нужно это недоразумение , если все намного проще ?
Люди, а ассемблер сложно учить? Может быть я реально зря на c (даж не c++) пишу...
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.
Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.
Ассемблер полезно представлять себе хотя бы затем, чтобы проверить, а чего же там намудрил компилятор. Потому как бывают варианты.
Ну и еще полезно представлять, во что именно выльется та или иная строка на Си. Потому как одна строка превращается в 2-3 оператора, которые выполняются 2-3 такта, а другая - ведет к вызову функции, которая может выполняться не одну тысячу тактов.
Ну да. Однако знать ассемблер, что бы посмотреть, что там намудрил компилятор не обязательно. Достаточно знать ассемблерные комаманды процессора - это необходимый минимум.
Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.
Для себя вы можете писать как угодно. Только критерии нужно установить - быстро, компактно, хитронакручено и т.д. Как правило, в большинстве случаев, это всё лишнее. Иначе, пишите на ассемблере.
Если выставляете на оценку - должны понимать что читают люди. А значит лаконично и понятно (а не хитрозакручено), правильно оформлено и переносимо.