ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 марта
897888 Топик полностью
Молодой коллега (20.01.2019 22:34, просмотров: 214) ответил Лагунов на Просто экстаз! STM32 - это очень просто. :-))))))))
10+ лет назад писано, i8051 - at89c2051. Стрелочные часы на граф. дисплее.  name main ;********************************************************************************* ; mail.asm; ; Эта программа подсчитывает время и выводит данные на lcd (96x65). ;********************************************************************************** $Include (C:\MyPrj\dat.asm) Extrn Code (init_lcd,clr_lcd,send_spi,change_co,lcd_norm_mode,lcd_inv_mode) Extrn Code (delay_1ms,delay_250ms) Extrn Code (start_i2c,send_i2c,read_i2c,read_i2c_no_ack,stop_i2c,read_one_byte,write_one_byte) main segment CODE rseg main ORG 0000H ; Начинаем программу с нулевого адреса jmp start ; Отсюда стартует программа после включения/сброса ORG 0003H jmp int_hour ; Внешнее прерывание 0 (по часовой кнопке) ORG 000BH jmp int_timer0 ; Прерывание по таймеру 0 ORG 0013H jmp int_minute ; Внешнее прерывание 1 (по минутной кнопке) ORG 001BH jmp int_timer1 ; Прерывания по таймеру 1 ORG 0023H reti ; Заглушка на вектор последовательному каналу ORG 0030H ; Сдесь будут подпрограммы ;########################################################## ;## Макросы ## ;########################################################## m_send_spi macro arg mov a,arg call send_spi endm m_change_co macro arg_x,arg_y mov r0,arg_x mov r1,arg_y call change_co endm m_send_i2c macro arg mov a,arg call send_i2c endm ;##################################################################### ; Подпрограммы ;##################################################################### ;********************************************************************* ; Процедура сложения двух 16-ых чисел ;********************************************************************* ; r7,r6 - слогаемое ; r5,r4 - слогаемое ; r5,r4 - сумма ;--------------------------------------------------------------------- add2_2: mov a,r6 add a,r4 mov r4,a mov a,r7 addc a,r5 mov r5,a ret ;********************************************************************* ; Процедура вычитания двух 16-ых чисел ;********************************************************************* ; R5,R4 - уменьшаемое ; R7,R6 - вычитаемоу ; R5,R4 - разность ;------------------------------------------------------------ sub2_2: mov a,r4 clr c subb a,r6 mov r4,a mov a,r5 subb a,r7 mov r5,a ret ;********************************************************************* ; Процедура увеличения 16-го числа на #00040h ;********************************************************************* ; r5,r4 - увеличиваемое число ; r5,r4 - результат ;--------------------------------------------------------------------- inc40h: mov a,#040h add a,r4 mov r4,a clr a addc a,r5 mov r5,a ret ;********************************************************************* ; Читать 65 байт и выводитьна экран (только для show_watch) ;********************************************************************* read_and_show_65: mov r4,#65 read_1s: call read_i2c call send_spi djnz r4,read_1s ret ;********************************************************************* ; Вывод на экран циферблата со стрелками ;********************************************************************* show_watch: mov r5,#001h ; Создание белой mov r4,#024h ; точки call read_one_byte ; в mov b,#0feh ; центре anl a,b ; экрана call write_one_byte ; (ось вращения стрелок) call start_i2c m_send_i2c #0a0h m_send_i2c #000h ; Адрес m_send_i2c #000h ; зеркала call start_i2c m_send_i2c #0a1h m_change_co #0,#0 mov r3,#8 nxt_shw2: call read_and_show_65 inc r1 call change_co djnz r3,nxt_shw2 mov r4,#64 read_sack2: call read_i2c call send_spi djnz r4,read_sack2 call read_i2c_no_ack call stop_i2c ret ;********************************************************************* ; Отображение заставки ;********************************************************************* title_lcd: m_change_co #0,#0 call start_i2c m_send_i2c #0a0h m_send_i2c #025h ; Адрес m_send_i2c #000h ; заставки call start_i2c m_send_i2c #0a1h ; Старт чтения mov r0,#0 mov r1,#0 mov r5,#9 ; 9x96 циклов next_read_title2: mov r4,#96 call change_co inc r1 next_read_title1: call read_i2c call send_spi call delay_1ms djnz r4,next_read_title1 djnz r5,next_read_title2 call read_i2c_no_ack call stop_i2c mov r4,#16 next_delay1: call delay_250ms djnz r4,next_delay1 ret ;********************************************************************* ; Сохранение 32-х байт из 24с256 в буфер ;********************************************************************* load_from_24c256: call start_i2c m_send_i2c #0a0h m_send_i2c high_adr_load m_send_i2c low_adr_load call start_i2c m_send_i2c #0a1h mov r4,#32 mov r0,#buffer next_red: call read_i2c mov @r0,a inc r0 djnz r4,next_red call read_i2c_no_ack mov @r0,a call stop_i2c ret ;********************************************************************* ; Запись 32-х байт в 24с256 из буфера ;********************************************************************* safe_to_24c256: call start_i2c m_send_i2c #0a0h m_send_i2c high_adr_safe m_send_i2c low_adr_safe mov r4,#32 mov r0,#buffer next_rec: mov a,@r0 call send_i2c inc r0 djnz r4,next_rec call stop_i2c ret ;********************************************************************* ; Процедура инкрементирования адресов 24с256 ;********************************************************************* inc_adr: mov r7,high_adr_load ; Увеличение mov r6,low_adr_load ; адреса mov r5,#0 ; источника mov r4,#32 ; на 32-мь call add2_2 ; байт mov high_adr_load,r5 ; mov low_adr_load,r4 ; mov r7,high_adr_safe ; Увеличение mov r6,low_adr_safe ; адреса mov r5,#0 ; приёмника mov r4,#32 ; на 32-мь call add2_2 ; байт mov high_adr_safe,r5 ; mov low_adr_safe,r4 ; ret ;********************************************************************* ; Саздание редактируемой копии картинки в памяти (зеркало) ;********************************************************************* miror_creation: mov high_adr_load,#07dh mov low_adr_load,#0afh mov high_adr_safe,#000h mov low_adr_safe,#000h mov r2,#18 next_copy: call load_from_24c256 call safe_to_24c256 call inc_adr djnz r2,next_copy ret ;********************************************************************* ; Процедура для преобразования координат дисплея в адрес 24с256 ; r4-x, r5-y <----->r5,r4-адрес ;********************************************************************* calculation_adr: mov a,#65 mov b,r5 mul ab mov r7,b mov r6,a mov r5,#0 call add2_2 ret ;********************************************************************* ; Чтение в буфер 64-х байт из 24с256 по адресу r5,r4 ;********************************************************************* read_to_buf: call start_i2c m_send_i2c #0a0h m_send_i2c r5 m_send_i2c r4 call start_i2c m_send_i2c #0a1h mov r4,#69 mov r0,#buffer next_reds: call read_i2c mov @r0,a inc r0 djnz r4,next_reds call read_i2c_no_ack mov @r0,a call stop_i2c ret ;##################################################################### ; Отрисовка стрелок, адрес стрелки в r5,r4 ;##################################################################### strelka: call read_to_buf ; Запись в ОЗУ из ПЗУ данных о стреке clr coord ; Сброс флага(если 0, то считать четвертый байт как колич. смен ко.) mov r0,#buffer ; Заносим в r0 указатель на буфер(ОЗУ) next_coord: mov a,@r0 ; Копируем в рег. r4 первый байт, inc r0 ; Инкремент адреса(ОЗУ) mov r4,a ; это X-я координата mov a,@r0 ; Копируем в рег. r5 второй байт, inc r0 ; Инкремент адреса(ОЗУ) mov r5,a ; это Y-я координата call calculation_adr ; Находим адрес этой области экрана в ПЗУ mov a,@r0 ; Чтение третьего байта, колич. байт данных до след смены ко. inc r0 mov r2,a jb coord,no_coor ; Переход если количество смен координат уже было прочитано mov a,@r0 ; Чтение четвёртого байта, количество смен координат inc r0 mov r3,a setb coord no_coor: next_data: mov b,@r0 ; Чтение пятого байта - это первый байт данных inc r0 call read_one_byte ; Чтение байта па адресу найденому calculation_adr orl a,b ; Наложение стрелки на фон call write_one_byte ; Запись байта па адресу найденому calculation_adr mov r7,#000h ; Увеличение mov r6,#001h ; адреса call add2_2 ; djnz r2,next_data djnz r3,next_coord ret ;********************************************************************* ; Процедура циклического инкриментирования адреса секундной стрелки ;********************************************************************* sec_adr_inc: mov r4,sec_low_adr mov r5,sec_high_adr cjne r5,#011h,sec_next_inc ; Проверка на то, что текущий адрес cjne r4,#040h,sec_next_inc ; это аднес 59-ой стрелки. mov r5,#002h ; Установка адреса mov r4,#080h ; 0-ой стрелки. mov sec_low_adr,r4 mov sec_high_adr,r5 setb sec_0 ret sec_next_inc: call inc40h mov sec_low_adr,r4 mov sec_high_adr,r5 ret ;********************************************************************* ; Процедура циклического инкриментирования адреса минутной стрелки ;********************************************************************* min_adr_inc: jb sec_0,min_inc mov r5,min_high_adr mov r4,min_low_adr ret min_inc: clr sec_0 mov r4,min_low_adr mov r5,min_high_adr cjne r5,#023h,min_next_inc ; Проверка на то, что текущий адрес cjne r4,#040h,min_next_inc ; это аднес 59-ой стрелки. mov r5,#014h ; Установка адреса mov r4,#080h ; 0-ой стрелки. mov min_low_adr,r4 mov min_high_adr,r5 setb min_0 ret min_next_inc: call inc40h mov min_low_adr,r4 mov min_high_adr,r5 ret ;********************************************************************* ; Процедура циклического инкриментирования адреса часовой стрелки ;********************************************************************* hour_adr_inc: jb min_0,hour_inc mov r4,hour_low_adr mov r5,hour_high_adr ret hour_inc: clr min_0 mov r4,hour_low_adr mov r5,hour_high_adr cjne r5,#014h,hour_next_inc ; Проверка на то, что текущий адрес cjne r4,#040h,hour_next_inc ; это аднес 11-ой стрелки. mov r5,#011h ; Установка адреса mov r4,#080h ; 0-ой стрелки. mov hour_low_adr,r4 mov hour_high_adr,r5 ret hour_next_inc: call inc40h mov hour_low_adr,r4 mov hour_high_adr,r5 ret ;##################################################################### ; Основная программа ;##################################################################### start: call init_lcd ; Инициализация экрана call clr_lcd ; Очистка экрана call title_lcd call clr_lcd ; Очистка экрана mov ie, #10001010b ; Регистр разрешения прерываний mov ip, #00001010b ; Регистр приоритетов прерываний mov tmod,#00010001b ; Регистр режимов Т/С mov th0,#013h ; начальная инициализация mov tl0,#048h ; таймера Т0 mov th1,#0ffh ; начальная инициализация mov tl1,#0dfh ; таймера Т1 setb tr0 ; запуск таймера Т0 call miror_creation mov sec_high_adr,#003h ; Начальная позиция mov sec_low_adr,#0c0h ; секундной стрелки mov min_high_adr,#01eh ; Начальная позиция mov min_low_adr,#080h ; минутной стрелки mov hour_high_adr,#012h ; Начальная позиция mov hour_low_adr,#000h ; часовой стрелки clr Green_LED background: mov ie, #10001111b ; Разрешения прерываний от кнопок когда нет др. задач nop jnb show,background ; Переход если флаг сброшен mov ie, #10001010b ; Запрет прерываний от кнопок call show_watch ; Отображение текущего времени call miror_creation call sec_adr_inc call strelka call min_adr_inc call strelka call hour_adr_inc call strelka clr show ; Сброс флага отображения jmp background ;##################################################################### ; Обработчикии прерываний ;##################################################################### int_timer0: ; Прерывание от таймета 0 mov th0,#013h mov tl0,#048h setb tr1 ; Запуск на один clr tr1 ; МЦ таймера 1 reti int_timer1: ; Прерывание от таймета 1 mov th1,#0ffh mov tl1,#0dfh setb show ; Установка флага, сигнал о необходимости отобразить время cpl White_LED cpl Green_LED reti int_hour: ; Внешнее прерывание 0 (по часовой кнопке) clr tr0 ; Остановка таймеров на время этого прерывания call lcd_inv_mode call miror_creation mov r5,sec_high_adr mov r4,sec_low_adr call strelka ; Отрисовка секундной стрелки в зеркале mov r5,min_high_adr mov r4,min_low_adr call strelka ; Отрисовка минутной стрелки в зеркале setb min_0 call hour_adr_inc ; Инкримент адреса часовой стрелки call strelka ; Отрисовка часовой стрелки в зеркале call show_watch call lcd_norm_mode setb tr0 ; Запуск таймеров reti int_minute: ; Внешнее прерывание 1 (по минутной кнопке) clr tr0 ; Остановка таймеров на время этого прерывания call lcd_inv_mode call miror_creation ; Создание зеркала mov r5,sec_high_adr mov r4,sec_low_adr call strelka ; Отрисовка секундной стрелки в зеркале clr min_0 mov r5,hour_high_adr mov r4,hour_low_adr call strelka ; Отрисовка часовой стрелки в зеркале setb sec_0 call min_adr_inc ; Инкримент адреса минутной стрелки call strelka ; Отрисовка минутной стрелки в зеркале call show_watch ; Отображение зеркала на дисплее call lcd_norm_mode setb tr0 ; Запуск таймеров reti ;##################################################################### ; Конец программы ;##################################################################### end