Перейти к содержанию

Вывод данных в прерывании через SPI


RIMUS1989i

Рекомендуемые сообщения

Здравствуйте. Написал код вывода данных посредством SPI в дисплей, обновление дисплея происходит посредством функции "MY9269_Refresh()", если поместить данную функцию вечный цикл main то все работает, но я хочу вывод поместить в прерывание, но там ничего не происходит. Как правильно инициализировать массив с данными и какой тип функции назначить чтобы данные в массиве обновлять в основном цикле, а выводить в прерывании?

Скрытый текст

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#include "pins.h"
#include "MY9269.h"
static uint8_t DATA_DISPLAY[DISPLAY_WIDTH][DISPLAY_HEIGHT][3];
  
void MY9269_Init()
{
	OUT(MY9269_MOSI);
	OUT(MY9269_SCK);
	OUT(MY9269_SS);

	CLR(MY9269_MOSI);
	CLR(MY9269_SCK);
	CLR(MY9269_SS);

	SPCR |=	(1<<SPE)|(1<<MSTR);//|(1<<CPHA); //SPI speed = fosc/2 = 20MHz/2
	SPSR |=	(1<<SPI2X);
}

void MY9269_sendData(uint8_t data)
{
	/* Так, как для MY9269 нужны данные 16бит, то мы просто посылаем два раза по 8бит. Младшие 8бит отправляются пустыми.
		Данные отправляются старшим битом вперед. */
	SPDR = data;					// Отправляем старшит байт
	while(!(SPSR & (1<<SPIF)));	
	SPDR = 0;					// Отправляем младший байт
	while(!(SPSR & (1<<SPIF)));
}

void MY9269_sendCommand(uint16_t data)
{
	SPDR = data >> 8;					// Отправляем старшит байт
	while(!(SPSR & (1<<SPIF)));	
	SPDR = data & 0xFF;					// Отправляем младший байт
	while(!(SPSR & (1<<SPIF)));
}

void MY9269_Latch()
{
	SET(MY9269_SS);
	CLR(MY9269_SS);
}

void MY9269_initLatch(uint8_t region)
{
	uint16_t reg = INVERT_BYTE(region);

	SET(MY9269_SS);
	MY9269_sendCommand(reg<<8); // выбираем область 1& 0xC000
	CLR(MY9269_SS);
	for(uint8_t i = 0; i < NUM_MY9269; i++)
		MY9269_sendCommand(COM_MY9269); // Отправляем команду на NUM_MY9269 микросхем
	MY9269_Latch();
}


void MY9269_Refresh()
{
	uint8_t nr = 0; //SCAN_APP_MY9269
	for(uint8_t r = 0; r < NUM_REGION; r++) // Отпраляем данные в области дисплея по порядку NUM_REGION
	{
		MY9269_initLatch(r); // Выбираем область и производим её настройку
		for(uint8_t x = 0; x < SCAN_APP_MY9269; x++) // Отправляем данные в выбраную область SCAN_APP_MY9269
		{
			for(uint8_t i = 0; i < UNUSED_PINS_MY9269; i++)MY9269_sendData(0); // Отправляем 0 на неиспользуемые каналы
			for(uint8_t y = 0; y < DISPLAY_HEIGHT; y++) 
			{
				MY9269_sendData(DATA_DISPLAY[x + nr][y][0]); // Отправляем уровень R
				MY9269_sendData(DATA_DISPLAY[x + nr][y][1]); // Отправляем уровень G
				MY9269_sendData(DATA_DISPLAY[x + nr][y][2]); // Отправляем уровень B
			}
			MY9269_Latch();
		}
		nr = nr + SCAN_APP_MY9269;
	}
	
}

 

основная программа с main

Скрытый текст

#define F_CPU 20000000UL
#include <avr/io.h>
#include <math.h>
#include <util/delay.h>
#include <stdio.h>
#include <inttypes.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <avr/pgmspace.h>

#include "pins.h"
#include "adc.c"
#include "MY9269.c"
#include "display.c"

uint8_t color[3]={0,0,200};
uint8_t color1[3]={252,0,0};
uint8_t peaks_speed=0;
static uint8_t peak[DISPLAY_WIDTH];


void timer_init()
{
	TCCR2B = (1 << CS22) | (0 << CS21) | (1 << CS20);
	TCCR2A = (1 << WGM21);
	OCR2A = 125;                                    // 125000/125 => 1000 polls/sec
	TCNT2 = 0;
	TIMSK2 |= (1 << OCIE2A);                        // Enable timer compare match interrupt
}

ISR (TIMER2_COMPA_vect)
{
	MY9269_Refresh(); // тут не работает
}

int main(void)
{
	adcInit();
	timer_init();
	MY9269_Init();
	
	
	sei();
    while(1)
    {
		
		clear_display();
		getSpData(0);
		peaks_speed==0?peaks_speed = 4:peaks_speed--;
		uint8_t x, xbase;
		uint8_t ybase;
		uint8_t btm=19 ;
		uint8_t val;
		uint8_t max=19;
		
		for (x = 0; x < DISPLAY_WIDTH; x++) { /
			xbase = x ;
			ybase = buf[x] + buf[x + 32];

			val = (ybase < max ? btm - ybase : btm - max);

			if(peaks_speed == 0)peak[x]++;
			if(peak[x]>=val)peak[x]=val;

			//if(peak[x]-->=val)peak[x]=val;
			
			draw_vert_line(xbase, btm, val, color);
			draw_pixel(xbase ,peak[x], color1);
		}
		
		//MY9269_RefreshRegion(2);
		//MY9269_Refresh(); Тут работает
		//_delay_ms(100);*/
    }
}

 

 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Прервать основную программу, зайти в прерывание и сделать что-то быстрое, например проверить состояние портов, и вернуться в основную программу.

Да я хочу долго сидеть в прерывании, но мне это нужно для эксперимента.

Ссылка на комментарий
Поделиться на другие сайты

Литиевые аккумуляторы EVE Energy и решения для управления перезаряжаемыми источниками тока (материалы вебинара)

Опубликованы материалы вебинара Компэл, посвященного литиевым аккумуляторам EVE Energy и решениям для управления перезаряжаемыми источниками тока.

На вебинаре мы представили информацию не только по линейкам аккумуляторной продукции EVE, но и по решениям для управления ею, что поможет рассмотреть эти ХИТ в качестве дополнительной альтернативы для уже выпускающихся изделий. Также рассмотрели нюансы работы с производителем и сервисы, предоставляемые Компэл по данной продукции. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

29 минут назад, RIMUS1989i сказал:

в прерывание и сделать что-то быстрое

ключевое слово "быстрое"

ставите флаг, а в цикле меин чекаете, если флаг есть рисуете, и сбрасываете.

типа

uint8_t updataFlags = 0;
прерывание() {
	updataFlags |= UPDATE_FLAG_DISP;
}

...
while (1) {
	if (updateFlags & UPDATE_FLAG_DISP) {
       перерисовать()
    }
}

ну или просто без функции прерывания проверяете системнй флаг нужного прерывания если оно есть в АВР, и перерисовываете 

Быстрое - это это то на пару тактов проца)) а не на пару десятков тысяч тактов

Изменено пользователем DrobyshevAlex
Ссылка на комментарий
Поделиться на другие сайты

@Eddy_Em 

Этот проект я перенес на STM32, но с DMA дела не имел. Как правильно организовать это все через DMA, не подскажите?

Скрытый текст

void MY9269_Refresh()
{
	uint8_t nr = 0; //SCAN_APP_MY9269
	for(uint8_t r = 0; r < NUM_REGION; r++) // Отпраляем данные в области дисплея по порядку NUM_REGION
	{
		MY9269_initLatch(r); // Выбираем область и производим её настройку
		for(uint8_t x = 0; x < SCAN_APP_MY9269; x++) // Отправляем данные в выбраную область SCAN_APP_MY9269
		{
			for(uint8_t i = 0; i < UNUSED_PINS_MY9269; i++)MY9269_sendData(0); // Отправляем 0 на неиспользуемые каналы
			for(uint8_t y = 0; y < DISPLAY_HEIGHT; y++) 
			{
				MY9269_sendData(DATA_DISPLAY[x + nr][y][0]); // Отправляем уровень R
				MY9269_sendData(DATA_DISPLAY[x + nr][y][1]); // Отправляем уровень G
				MY9269_sendData(DATA_DISPLAY[x + nr][y][2]); // Отправляем уровень B
			}
			MY9269_Latch();
		}
		nr = nr + SCAN_APP_MY9269;
	}
	
}

 

 

Задача равномерно по времени вызывать MY9269_initLatch(r), после отправлять данные из массива, 

Изменено пользователем RIMUS1989i
Ссылка на комментарий
Поделиться на другие сайты

19 minutes ago, RIMUS1989i said:

не подскажите?

Занятный вопрос, я не понял, что он означает (почему это меня просят не подсказывать?).

Вот так я работаю с экранчиком на MAX7219. Передача данных посредством DMA, если обновил буфер и нужно обновить экран в соответствии с этим, выставляю соответствующее значение конечного автомата. Если у вас буфер обновляется очень часто, можно в КА убрать состояние RELAX и как только отправлен последний байт из буфера экрана, переходить к началу.

Ссылка на комментарий
Поделиться на другие сайты

  • 3 недели спустя...
25.03.2021 в 16:36, RIMUS1989i сказал:

void MY9269_sendData(uint8_t data)

вот эту функцию надо вызывать в прерывании

Изменено пользователем ruhi
не все можно рассказать

Можно сделать все! Но чем больше можно, тем больше нельзя!

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...