Вопросы начинающих PIC ASM

Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Доброго времени суток. Снова я со свои программным UART-ом. Никак не получается написать прием на прерываниях. Ниже код, в нем есть закоментированый кусок передачи лат. символа "А", он работает нормально. Тоесть передача работает нормально (она пока не на прерываниях, всему свое время). Проблема возникает, когда пытаюсь передавать символ, который принял (в прерывании) - передает не то, что отправлял в терминале. Просьба подсказать, где ошибка.
Спойлер

Код: Выделить всё

	list p=16f629
	__config	_CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDTE_OFF & _FOSC_INTRCIO
	include	p12f629.inc

#define RX_		2
#define TX_		1
#define	RX	GPIO,RX_					; В качестве приемника может быть только эта ножка
#define	TX	GPIO,TX_					; А вот в качестве передатчика можем назначить любую, даже ту же				

#define	BITS_DELAY	.30					; Задержка длинной 1 бит - 104 мкс при 9600 бод и частоте 4 МГц
#define	RX_Complete	0					; Флаг завершения приема

; В прерывании только прием байта (побитно), и выставление флага окончания приема, который уже анализируется в основном цикле
;======================
Soft_UART	udata_shr
w_temp			res	1
status_temp		res	1
TX_byte			res	1
RX_byte			res	1
UART_counter	res	1
delay_counter	res	1
Flags			res	1
;======================
push	macro
;	movwf	w_temp
;	swapf	STATUS,w
;	movwf	status_temp

	movwf	w_temp						; save off current W register contents
	movfw	STATUS						; move status register into W register
	movwf	status_temp					; save off contents of STATUS register
	endm

pop		macro
;	swapf	status_temp,w
;	movwf	STATUS
;	swapf	w_temp,f
;	swapf	w_temp,w

	movfw	status_temp					; retrieve copy of STATUS register
	movwf	STATUS						; restore pre-isr STATUS register contents
	swapf	w_temp,f
	swapf	w_temp,w					; restore pre-isr W register contents
	endm
;======================
RESET_VECTOR	code	0h
	goto	Ini
;======================
ISR				code	4h				; Вектор прерывания
Interrupt_Heandler
	push								; Сохраним контекст
	btfsc	INTCON,INTF			
	goto	Start_bit					; Если есть флаг внешнего прерывания - пришел старт-бит
	btfsc	INTCON,T0IF				
	goto	Receive_bit					; Если флаг таймера, значит принимаем очередной бит посылки			
End_Interrupt_Heandler
	pop									; Восстановим контекст	
	retfie
;======================
Start_bit
	bcf		INTCON,INTF					; Сбросим флаг внешнего прерывания
	movlw	.191						; Перезапишем таймер для периода переполнения в 156 мкс (середина 1 бита данных)
	movwf	TMR0
	movlw	.8							; Загрузим количество принимаемых битов
	movwf	UART_counter
	clrf	RX_byte						; Очистим приемник
	bcf		INTCON,INTE					; Запрещаем внешнее прерывание (4 бит)
	bsf		INTCON,T0IE					; Разрешаем прерывание по переполнению Таймера 0 (5 бит)
	bcf		INTCON,T0IF					; Сбросим флаг переполнения Таймера 0, он почти наверняка переполнился, пока мы ждали старт-бит
	goto	End_Interrupt_Heandler	
;======================
Receive_bit
	movlw	.211						; Перезапишем таймер для периода переполнения в 104 мкс
	movwf	TMR0
	bcf		INTCON,T0IF					; Сбросим флаг переполнения Таймера 0
	bcf		STATUS,C					; Сбросим бит переноса
	rrf		RX_byte						; Задвигаем сброшеный бит переноса в приемный регистр
	btfsc	RX							; А теперь проверяем, что на самом деле надо было туда задвинуть
	bsf		RX_byte,7					; Если 1, надо срочно подкорректировать, ведь мы задвинули 0
	decfsz	UART_counter				; Весь байт принят ?
	goto	End_Interrupt_Heandler		; Нет, идем принимать следующий бит
	bsf		Flags,RX_Complete			; Поставим флажок окончания приема байта			
	bcf		INTCON,T0IE					; Запрещаем прерывание по переполнению Таймера 0 (5 бит)		
	bsf		INTCON,INTE					; Разрешаем внешнее прерывание (4 бит) для приема следующего старт-бита
	goto	End_Interrupt_Heandler		; На выход
;======================
Ini
	clrf	Flags						; Сбросим все флаги
	movlw	b'111111'					; Заранее установим необходимые уровни на выходах, чтобы в момент переключения с входов на выходы му уже имели на них нужные значения
	movwf	GPIO						; Init GPIO	
	banksel	OSCCAL						; Bank 1
	call	3FFh
	movwf	OSCCAL
if	RX_ != TX_		
	bcf		TX							; Настроим TX на выход
endif
	movlw	b'11000000'					; Подтягивающие резисторы включены, внешнее прерывание по переднему фронту, тактирование Таймера 0 от внутреннего генератора, пределитель 1 к 2, что дает 512 мкс на частоте 4 Мгц
	movwf	OPTION_REG
	banksel	GPIO						; Bank 0	
	movlw	b'00000111'
	movwf	CMCON						; Выключим аналоговый компаратор
	movlw	b'10010000'					; Разрешаем прерывания вообще (7 бит) и внешнее прерывание (4 бит) 
	movwf	INTCON
;======================
;	movlw	'A'
;	call	Send_TX_byte
Main
;	goto	Main

	btfss	Flags,RX_Complete			; Анализируем флажок приема байта
	goto	Main						; Нет флажка - нет принятого байта			
	movfw	RX_byte						; Засунем принятый байт в рабочий регистр
	call	Send_TX_byte				; И отправим назад
	bcf		Flags,RX_Complete			; Скинем флажок принятого байта
	goto	Main
;======================
Send_TX_byte							; Подпрограмма передачи 1 байта
	bcf		INTCON,GIE					; Запрещаем прерывания	
if	RX_ == TX_	
	banksel	TRISIO						; Bank 1
	bcf		TX							; Настроим TX на выход
	banksel	GPIO						; Bank 0
endif
;-----------------------------------------------------------------------------------------------
	bcf		TX							; Шлем старт бит
	movwf	TX_byte						; Загрузим передавемый байт			
	movlw	.8							; Загрузим количесвто передаваемых битов
	movwf	UART_counter
	nop
Transmit_Next_Bit
	nop
	call	Delay_1bit					; Длинной 1 бит
	rrf		TX_byte						; Продвигаем в бит переноса все биты, начиная с младшего
	btfsc	STATUS,C					; Проверяем, что выдавилось в бит переноса
	bsf		TX							; Если 1, выставляем 1 на ТХ
	btfss	STATUS,C
	bcf		TX							; Если 0, выставляем 0 на ТХ
	decfsz	UART_counter				; Весь байт отослан ?
	goto	Transmit_Next_Bit			; Нет, идем слать следующий бит
	call	Delay_1bit					; Задержка длинной 1 бит
	nop
	nop
	nop
	nop
	nop
	bsf		TX							; Шлем стоп-бит
	call	Delay_1bit					; Задержка длинной 1 бит
;-----------------------------------------------------------------------------------------------
if	RX_ == TX_	
	banksel	TRISIO						; Bank 1
	bsf		TX							; Настроим ножку на вход
	banksel	GPIO						; Bank 0
endif
	bcf		INTCON,T0IF					; Сбросим флаг переполнения Таймера 0
	bcf		INTCON,INTF					; Сбросим флаг внешнего прерывания
	bsf		INTCON,GIE					; Разрешаем прерывания
	return
;======================
Delay_1bit
	movlw	BITS_DELAY					; 104 мкс для 9600 бод
	movwf	delay_counter
Loop_Delay
	decfsz	delay_counter
	goto	Loop_Delay
	return
	
	end
Последний раз редактировалось Пока_без_кота Вт авг 23, 2016 12:00:32, всего редактировалось 1 раз.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15600
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Снова повторяю напоминание -
необходимо использовать штатный шаблон для обработчика прерываний
(
; MOVWF W_TEMP ; save off current W register contents
; MOVF STATUS,w ; move status register into W register
; MOVWF STATUS_TEMP ; save off contents of STATUS register

здесь собственно прожка

; MOVF STATUS_TEMP,w ; retrieve copy of STATUS register
; MOVWF STATUS ; restore pre-isr STATUS register contents
; SWAPF W_TEMP,f
; SWAPF W_TEMP,w ; restore pre-isr W register contents
; RETFIE ; return from interrupt
)
ИБО... W и STATUS требуют предварительного сохранения и последующего восстановления!
а чего у Вас в макросах (push & pop)? :wink:
Это минимум - глубше не вникал.
:roll:
Помимо прочего не рекомендую злоупотреблять
#define
в тех случаях, когда более оправданно-понимаемо применение стандартных директив
equ
и других...
8)
Реклама
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

BOB51 писал(а):... а чего у Вас в макросах (push & pop)? :wink:
Дык у меня вроде то же самое аналогичное по функционалу, взято из книжки:
push macro
movwf w_temp
swapf STATUS,0
movwf status_temp
endm

pop macro
swapf status_temp,0
movwf STATUS
swapf w_temp,1
swapf w_temp,0
endm

Изображение
Друг Кота
Аватара пользователя
Сообщения: 15600
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

То книжка от вредоносного СУСАНИНА - ибо копируется в программный стек содержимое W и STATUS без разворотов, а вот при восстановлении хитрый SWАP применяется для того, чтобы содержимое флажков в STATUS не испортить прямым загрузом W из регистра временного хранения (точно по каким соображениям - ШКЛЕРОЗЬ - смотреть конспехты надо /сейчас мозги АВРкой забиты).
:?
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Сделал по-вашему, ничего не изменилось. Скорее всего дело не в этом, я где-то в алгоритме или его реализации накосячил.
Что уже обнаружил и исправил:
Внешнее прерывание перенастроил по переднему фронту (установил 6 бит в OPTION при инициализации). Но это еще не все, есть что-то еще.
Алгоритм следующий:
1. Жду прерывание на внешней ноге.
2. Захожу в обработчик по внешнему прерыванию, настраиваю таймер на прерывание через полтора бита (середина 1 бита данных), инициализирую счетчик битов, запрещаю внешнее прерывание, разрешаю прерывание по таймеру.
3. Захожу в обработчик по прерыванию таймера, настраиваю таймер на перывание через 1 бит, принимаю бит, уменьшаю счетчик, если не 0, просто выхожу.
4. Если счетчик 0, выставляю флажок окончания приема, запрещаю прерывание по таймеру, разрешаю внешнее прерывание для следующего старт бита.

Вроде все верно ?
Реклама
abc
Друг Кота
Аватара пользователя
Сообщения: 3687
Зарегистрирован: Чт мар 20, 2008 01:06:40
Откуда: Севастополь

Сообщение abc »

Верно.
Только кто ж будет разбираться с этим дальше ?
Тут действующих программистов под PIC - полтора человека :)
А PIC12F1822 стоит дешевле, чем то время, что они потратят на анализ вашего кода.
>(*.*)<
Котище огромно, ушасто, пушисто, глазасто, зубасто, колючелапо и мявай. (c)
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15600
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

abc писал(а):...
А PIC12F1822 стоит дешевле, чем то время, что они потратят на анализ вашего кода.
А Вам отличия по ассемблеру для PIC12F1822 известны?
Человек еще с "стандартным среднемладшим" еще не разобрался, а тут гибрид 18-й серии.
Как по структуре ядра, так и по системе команд (не говоря уже о необходимости иметь программатор с регулировками напряжения прошивки и соответствующие дополнения по самой IDE - в "штатном" 8.92 это семейство только начинает рассматриваться к применению).
Да и не у всех доступ к столь широкому ассортименту имеется.
8)
Закончу тест-заготовку под WS2812 можно будет и отвлечся...
:beer:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Вы пишите о проблеме с передачей :
Пока_без_кота писал(а):Проблема возникает, когда пытаюсь передавать символ, который принял (в прерывании) - передает не то, что отправлял в терминале. Просьба подсказать, где ошибка
А алгоритм приводите приёма :
Пока_без_кота писал(а):1. Жду прерывание на внешней ноге.2. Захожу в обработчик по внешнему прерыванию, настраиваю таймер на прерывание через полтора бита (середина 1 бита данных),
...........
Как это понимать ? И в чём конкретно проблема, в передаче или приёме ? :dont_know:
Контактная информация:
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Аlex писал(а):Как это понимать ? И в чём конкретно проблема, в передаче или приёме ? :dont_know:
Прошу прощения, нечетко выражаю мысли.
Проблема именно в приеме. Передача у меня реализована пока не в прерыаниях, она уже опробована и с ней проблем нет, у меня есть в программе закомментированые строчки:

Код: Выделить всё

;	movlw	'A'
;	call	Send_TX_byte
Main
;	goto	Main
Если их раскомментировать, то в этом месте происходит передача ASCII кода англ. символа "А" и зацикливание программы, из чего я делаю вывод, что передача у меня работает корректно. Проблема в том, что если я включаю прием на прерываниях, то назад в компьютер передается не тот символ, который я отправлял в контроллер. Значит проблема в приеме :)))
Друг Кота
Аватара пользователя
Сообщения: 15600
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Возможно ошибка не в прерывании, а в согласовании обмена (принятом протоколе для связи МК и ПК).
Принимать/отправлять "просто так" в компе только простейшие терминальные прожки могут.
:dont_know:
А может и алгоритм не совсем корректен - включи логический анализатор(в МПлабе) и посмотри чего там происходит в пошагово в дебаггере.
:roll:
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Ну, на стороне ПК с прогой проблем я думаю нет, потому что когда прием был написан не на прерывании мне контроллер возвращал тот символ, который я ему отправлял.
А дебагером я и отлаживал сперва (прежде чем вопить здесь о помощи :oops: ), НОП-ы ставил как раз для того, чтобы подобрать точные задержки при передаче (104 мкс между битами). При отладке в дебагере у меня точно выдерживаються все временные интевалы. Процесс отладки выглядит так:
1. Запускаю прогу на выполнение, жду немного, ставлю на паузу.
2. Выставляю 1 бит в INTCON. Опять запускаю на выполнение.
3. Захожу в прерывание по INT (стоит брекпоинт), запускаю секундомер, выхожу.
4. На момент считывания бита по таймеру у меня стоит точка отладки, до нее от момента входа в прерывание INT ровно 156 мкс.
5. Потом между моментами считывания бита по переполнению таймера у меня ровно 104 мкс. Стоп-бит я не ловлю.
Друг Кота
Аватара пользователя
Сообщения: 15600
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Анализатор векторов и сама обработка прерываний весьма неудачна.
Возможны "гонки" источников прерываний - при исполнении внешнего прерывания "перекрывается" таймер и наоборот.
Лучше использовать флаг-транслятор вместо INTCON,T0IF (T0IF лишь отметка времени, а требование исполнения - дополнительный флаг, сбрасываемый уже исполнительной прожкой).
Да и обращение с самим таймером - смена значения "на лету" не есть хорошо - сначала стоп счета, затем запись и затем пуск будет стабильнее работать (здесь нет буфера для синхронного переноса данных).
При необходимости оперативного изменения "плавающего коэффициента счета" у ПИКа используется TMR1 в режиме "Сброс TMR1 триггером модуля CCP"
:roll:
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

BOB51 писал(а):Анализатор векторов и сама обработка прерываний весьма неудачна... :roll:
Спасибо, переделал, все работает !!!!
Сижу и думаю, как я мог такое написать, ведь действительно источники прерываний "перекрывали" друг друга. Просто до этого не имел дела со множеством прерываний на 1 векторе, немного непривычно :)))
Результирующий код:
Спойлер

Код: Выделить всё

	list p=16f629
	__config	_CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDTE_OFF & _FOSC_INTRCIO
	include	p12f629.inc

#define RX_		2
#define TX_		1
#define	RX	GPIO,RX_					; В качестве приемника может быть только эта ножка
#define	TX	GPIO,TX_					; А вот в качестве передатчика можем назначить любую, даже ту же				

#define	BITS_DELAY	.30					; Задержка длинной 1 бит - 104 мкс при 9600 бод и частоте 4 МГц
#define	RX_Complete			0			; Флаг завершения приема
#define Receive_in_Process	1			; Флаг-признак процесса приема байта

; В прерывании только прием байта (побитно), и выставление флага окончания приема, который уже анализируется в основном цикле
;======================
Soft_UART	udata_shr
w_temp			res	1
status_temp		res	1
TX_byte			res	1
RX_byte			res	1
UART_counter	res	1
delay_counter	res	1
Flags			res	1
;======================
push	macro
;	movwf	w_temp
;	swapf	STATUS,w
;	movwf	status_temp

	movwf	w_temp						; save off current W register contents
	movfw	STATUS						; move status register into W register
	movwf	status_temp					; save off contents of STATUS register
	endm

pop		macro
;	swapf	status_temp,w
;	movwf	STATUS
;	swapf	w_temp,f
;	swapf	w_temp,w

	movfw	status_temp					; retrieve copy of STATUS register
	movwf	STATUS						; restore pre-isr STATUS register contents
	swapf	w_temp,f
	swapf	w_temp,w					; restore pre-isr W register contents
	endm
;======================
RESET_VECTOR	code	0h
	goto	Ini
;======================
ISR				code	4h				; Вектор прерывания
Interrupt_Heandler
	push								; Сохраним контекст
	btfsc	Flags,Receive_in_Process				
	goto	Receive_bit					; Если флаг-признак процесса приема бита установлен - принимаем очередной бит посылки					
	btfsc	INTCON,INTF							
	goto	Start_bit					; Если есть флаг внешнего прерывания - пришел старт-бит						
End_Interrupt_Heandler
	bcf		INTCON,T0IF					; Сбросим флаг переполнения Таймера 0
	bcf		INTCON,INTF					; Сбросим флаг внешнего прерывания
	pop									; Восстановим контекст	
	retfie
;======================
Start_bit
	movlw	.190						; Перезапишем таймер для периода переполнения в 156 мкс (середина 1 бита данных)
	movwf	TMR0
	movlw	.8							; Загрузим количество принимаемых битов
	movwf	UART_counter
	clrf	RX_byte						; Очистим приемник
	bsf		Flags,Receive_in_Process	; Установим флаг-признак процесса приема байта
	bcf		INTCON,INTE					; Запрещаем внешнее прерывание (4 бит)
	bsf		INTCON,T0IE					; Разрешаем прерывание по переполнению Таймера 0 (5 бит)
	goto	End_Interrupt_Heandler	
;======================
Receive_bit
	movlw	.210						; Перезапишем таймер для периода переполнения в 104 мкс
	movwf	TMR0
	bcf		STATUS,C					; Сбросим бит переноса
	rrf		RX_byte						; Задвигаем сброшенный бит переноса в приемный регистр
	btfsc	RX							; А теперь проверяем, что на самом деле надо было туда задвинуть
	bsf		RX_byte,7					; Если 1, надо срочно подкорректировать, ведь мы задвинули 0
	decfsz	UART_counter				; Весь байт принят ?
	goto	End_Interrupt_Heandler		; Нет, идем принимать следующий бит
	bcf		Flags,Receive_in_Process	; Сбросим флаг-признак процесса приема байта
	bsf		Flags,RX_Complete			; Поставим флажок окончания приема байта			
	bcf		INTCON,T0IE					; Запрещаем прерывание по переполнению Таймера 0 (5 бит)		
	bsf		INTCON,INTE					; Разрешаем внешнее прерывание (4 бит) для приема следующего старт-бита
	goto	End_Interrupt_Heandler		; На выход
;======================
Ini
	clrf	Flags						; Сбросим все флаги
	movlw	b'111111'					; Заранее установим необходимые уровни на выходах, чтобы в момент переключения с входов на выходы му уже имели на них нужные значения
	movwf	GPIO						; Init GPIO	
	banksel	OSCCAL						; Bank 1
	call	3FFh
	movwf	OSCCAL
if	RX_ != TX_		
	bcf		TX							; Настроим TX на выход
endif
	movlw	b'10000000'					; Подтягивающие резисторы включены, внешнее прерывание по заднему фронту, тактирование Таймера 0 от внутреннего генератора, пределитель 1 к 2, что дает 512 мкс на частоте 4 Мгц
	movwf	OPTION_REG
	banksel	GPIO						; Bank 0	
	movlw	b'00000111'
	movwf	CMCON						; Выключим аналоговый компаратор
	movlw	b'10010000'					; Разрешаем прерывания вообще (7 бит) и внешнее прерывание (4 бит) 
	movwf	INTCON
;======================
	bcf		Flags,Receive_in_Process	; Сбросим флаг-признак процесса приема байта

;	movlw	'A'
;	call	Send_TX_byte
Main
;	goto	Main

	btfss	Flags,RX_Complete			; Анализируем флажок приема байта
	goto	Main						; Нет флажка - нет принятого байта			
Wait_Receive_complete
	btfss	RX							; Ожидаем стоп бит
	goto	Wait_Receive_complete	
	movfw	RX_byte						; Засунем принятый байт в рабочий регистр
	call	Send_TX_byte				; И отправим назад
	bcf		Flags,RX_Complete			; Скинем флажок принятого байта
	goto	Main
;======================
Send_TX_byte							; Подпрограмма передачи 1 байта
	bcf		INTCON,GIE					; Запрещаем прерывания	
if	RX_ == TX_	
	banksel	TRISIO						; Bank 1
	bcf		TX							; Настроим TX на выход
	banksel	GPIO						; Bank 0
endif
;-----------------------------------------------------------------------------------------------
	bcf		TX							; Шлем старт бит
	movwf	TX_byte						; Загрузим передаваемый байт			
	movlw	.8							; Загрузим количество передаваемых битов
	movwf	UART_counter
	nop
Transmit_Next_Bit
	nop
	call	Delay_1bit					; Длинной 1 бит
	rrf		TX_byte						; Продвигаем в бит переноса все биты, начиная с младшего
	btfsc	STATUS,C					; Проверяем, что выдавилось в бит переноса
	bsf		TX							; Если 1, выставляем 1 на ТХ
	btfss	STATUS,C
	bcf		TX							; Если 0, выставляем 0 на ТХ
	decfsz	UART_counter				; Весь байт отослан ?
	goto	Transmit_Next_Bit			; Нет, идем слать следующий бит
	call	Delay_1bit					; Задержка длинной 1 бит
	nop
	nop
	nop
	nop
	nop
	bsf		TX							; Шлем стоп-бит
	call	Delay_1bit					; Задержка длинной 1 бит
;-----------------------------------------------------------------------------------------------
if	RX_ == TX_	
	banksel	TRISIO						; Bank 1
	bsf		TX							; Настроим ножку на вход
	banksel	GPIO						; Bank 0
endif
	bcf		INTCON,T0IF					; Сбросим флаг переполнения Таймера 0
	bcf		INTCON,INTF					; Сбросим флаг внешнего прерывания
	bsf		INTCON,GIE					; Разрешаем прерывания
	return
;======================
Delay_1bit
	movlw	BITS_DELAY					; 104 мкс для 9600 бод
	movwf	delay_counter
Loop_Delay
	decfsz	delay_counter
	goto	Loop_Delay
	return
	
	end
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Доброго времени суток. Подскажите пожалуйста, как объявить переменную в EEPROM-памяти, чтобы значение в нее заносилась на этапе компиляции программы (и получался отдельный файл для EEPROM), и потом, при прошивке МК просто надо было прошить EEPROM, и получить там нужное значение. Можно конечно вручную выбрать View - EEPROM и там в нужную ячейку внести все ручками, но хотелось бы, чтобы все делалось само на автомате.
Нашел директиву DE, но там пример какой-то не совсем понятный:

Код: Выделить всё

org H'2100'
de  <value>
Это вроде как для абсолютного кода. Как мне быть, если у меня перемещаемые сегменты кода (проект состоит из нескольких файлов) ?

Ап: 2 botchin - спасибо, получилось :beer:
Теперь найти бы опцию в MPLAB, чтобы обновлять все содержимое EEPROM после компиляции, а то я сделал адрес H'2101', компильнул - там стало нужное значение, потом вернул адрес H'2100', опять компильнул, там тоже стало нужное значение, но и по адресу H'2101' осталось старое :roll: Ручками что-ли затирать ???
Последний раз редактировалось Пока_без_кота Вс авг 28, 2016 21:10:50, всего редактировалось 5 раз.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Сообщение botchin »

Я на 16F628А делаю так

Код: Выделить всё

;EEPROM данни
	ORG 0X2100
;sHZ	DE	'H','z',0x00				; 0x00 
sind de 0xa5,0xbd,0xe3,'y',0xba,0xbf,0xb8,0xb3,0xbd,'o','c',0xbf,0x00	;0x03	
sFreq	DE	0xab,'e','c',0xbf,'o',0xbf,'a',0x00			;0x24 - честота
shello	DE	0xa4,0xe3,'p','a',0xb3,'e',0xb9,0x00		;0x2c - Здравей
sname  	DE	'B','a',0xbb,'e','p',0xb8,0xb9,0x00			; Валерий

;ds18b20_1 de 0x28,0x8a,0xba,0x0e,0x02,0x00,0x00,0x93	;0x93 - CRC
;ds18b20_2 de 0x28,0xcc,0x94,0x0e,0x02,0x00,0x00,0x0e	;0x0e - CRC
stemp	de ' ','B',0xc2,0xbd,0x00			;Вън
stemp1	de 	'B',0xc2,0xbf,'p','e',0x00		;Вътре
ds1	de 0xa1,0,0,0x02,0x0e,0xad,0xee,0x28
ds2 de 0x0e,0,0,0x02,0x0e,0x94,0xcc,0x28
ccp_1 de 0xff, 0xff, 0xff, 0xff
ccp_2 de 0xff, 0xff, 0xff, 0xff
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Теперь найти бы опцию в MPLAB, чтобы обновлять все содержимое EEPROM после компиляции, а то я сделал адрес H'2101', компильнул - там стало нужное значение, потом вернул адрес H'2100', опять компильнул, там тоже стало нужное значение, но и по адресу H'2101' осталось старое Ручками что-ли затирать ???
Только ручками.
Причём там это делается всё в пару кликов. Правая кнопка мыши, и выбираем что-то типа "fill memory", или что-то в этом роде. Вводим значение и все ячейки заполняются этим значением.
Контактная информация:
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Аlex писал(а):Только ручками...
Спасибо, все равно достаточно удобно. Всяко лучше, чем каждую вручную перебивать :)))
Друг Кота
Аватара пользователя
Сообщения: 15600
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Директива DE одинакова как для абсолютного, так и для относительного режимов адресации (то же касается и директив разметки таблиц/данных в ПЗУ) - там будет выполнено или явное указание адреса или "склеивание" с последним предшествующим значением.
Отличия будут только в синтаксисе МК/МП при совмещенной памяти программ/данных (STM8 и I8080-подобных) и то в плане дополнительных директив/префиксов-суффиксов обработки сегментов ("склейка", наложение/перекрытие и прочие...). Для mcs51, avr, pic директивы размещения таблиц/данных действуют одинаково (иногда наблюдаются отличия в названии директив).
8)
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Спасибо за разъяснение :roll:
Теперь такой вопрос. Есть у меня запись в EEPROM внутри программы. При этом я жду окончания записи тупым циклом с задержкой. Хотелось бы сделать это красивее, и например поспать в это время :))) Но при этом не хочется усложнять обработчик прерываний, потому что это процедура довольно редкая, и не хотелось бы в обработчике городить еще проверку и сброс флага EEIF. Вычитал что "микроконтроллер выходит из режима SLEEP независимо от состояния бита GIE. Если GIE=0 выполняется следующая инструкция после SLEEP, без перехода по вектору прерываний". Отлично, то что надо, могу поспать, и в обработчик лезть не надо, делаю так:

Код: Выделить всё

; где то в начале инициализации
	bsf		INTCON,PEIE					; Разрешаем прерывания от периферии
	bsf		PIE1,EEIE					; Разрешаем прерывания по окончанию записи в EEPROM	

;	много кода    

;	Здесь запись в EEPROM, прерывания запрещены
	sleep								; Засыпаем в ожидании завершения записи
	nop
	bcf		PIR1,EEIF					; Просыпаемся, и сбросываем флаг окончания записи в EEPROM, чтобы не переходить в обработчик после разрешения прерываний
	bsf		INTCON,GIE					; Разрешаем прерывания, но не переходим на обработчик прерываний, посколькe флаг уже сброшен
;	Продолжаем выполнение программы с удачно завершенной записью
И не работает оно почему-то :roll:
Друг Кота
Аватара пользователя
Сообщения: 4119
Зарегистрирован: Чт сен 12, 2013 00:54:12
Откуда: ЗаМКАДье. Там, где ЦУП

Сообщение Albert_V »

Пока_без_кота писал(а):...Вычитал что "микроконтроллер выходит из режима SLEEP независимо от состояния бита GIE. Если GIE=0 выполняется следующая инструкция после SLEEP, без перехода по вектору прерываний"...
Дайте ссылку на этот "документ".
----
Если прерывания не разрешены - из спячки по INT не выйдет.
Это указано в pdf-е и подтверждено практикой.
Ответить

Вернуться в «PIC»