В почти каждом шрифте это решение будет работать.
Если вы создаете этот текст:
imagettftext($jpg_image, 35, 0, $x, $y, $color, $font_path, $text2);
, и если вам нужен жирный шрифт, вы должны добавить следующее:
imagettftext($jpg_image, 35, 0, $x, $y, $color, $font_path, $text2);
imagettftext($jpg_image, 35, 0, $x, $y+1, $color, $font_path, $text2);
imagettftext($jpg_image, 35, 0, $x, $y+2, $color, $font_path, $text2);
imagettftext($jpg_image, 35, 0, $x+1, $y, $color, $font_path, $text2);
imagettftext($jpg_image, 35, 0, $x+2, $y, $color, $font_path, $text2);
В портах AVR имеются специальные регистры ввода-вывода, доступ к которым осуществляется с помощью инструкций IN и OUT. Не как память с использованием LDR и т. Д.
Из определения порта вы можете видеть, что вам нужно сделать указатель порта энергозависимым. что компилятор также сказал бы вам как предупреждение, когда вы попытались бы передать PORT в функцию.
#define PORTB _SFR_IO8(0x05)
, который отображается на
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
Различные вопросы:
void debounceSwitch(volatile uint8_t* port, uint8_t pin)
. Указатели на аппаратные регистры всегда должны быть volatile
. Не имеет смысла что-либо возвращать. 1
литералы со знаком int
при сдвиге битов. Должно быть 1u << n
, иначе ваша программа выдаст ошибку, если n
больше 8. Есть много способов отменить кнопки. Простейшая профессиональная форма, вероятно, состоит в том, чтобы иметь периодический таймер, работающий с прерыванием каждые 10 мс (этого должно быть достаточно, если сомневаетесь, измерьте шипы отклонения вашей кнопки с областью действия). Это будет выглядеть примерно так: псевдокод:
volatile bool button_pressed = false;
void timer_interrupt (void)
{
uint8_t button = port & mask;
button_pressed = button && prev;
prev = button;
}
Это при условии, что кнопки используют активную высокую логику.
Что мне не нравится в вашей реализации, так это чистая зависимость от обработки PORT / IO и действительной логики фильтрации / устранения неполадок. Что вы делаете тогда, когда на вход переключателя поступает сигнал, например, от CAN?
Кроме того, это может быть обработано намного проще, если вы думаете о настраиваемых / параметризуемых фильтрах. Вы реализуете логику один раз, а затем просто создаете надлежащие конфиги и передаете отдельные переменные состояния в фильтр.
// Structure to keep state
typedef struct {
boolean state;
uint8 cnt;
} deb_state_t;
// Structure to configure the filters debounce values
typedef struct {
uint8 cnt[2]; // [0] = H->L transition, [1] = L->H transition
} deb_config_t;
boolean debounce(boolean in, deb_state_t *state, const deb_config_t *cfg)
{
if (state->state != in) {
state->cnt++;
if (state->cnt >= cfg->cnt[in]) {
state->state = in;
state->cnt = 0;
}
} else {
state->cnt = 0;
}
return state->state;
}
static const deb_config_t debcfg_pin = { {3,4} };
static const deb_config_t debcfg_can = { {2,1} };
int main(void)
{
boolean in1, in2, out1, out2;
deb_state_t debstate_pin = {0, 0};
deb_state_t debstate_can = {0, 0};
while(1) {
// read pin and convert to 0/1
in1 = READ_PORT(PORTx, PINxy); // however this is defined on this architecture
out1 = debounce(in1, &debstate_pin, &debcfg_pin);
// same handling, but input from CAN
in2 = READ_CAN(MSGx, SIGxy); // however this is defined on this architecture
out2 = debounce(in2, &debstate_can, &debcfg_can);
// out1 & out2 are now debounced
}