Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: Вопросы по С/С++ (СИ)

Сообщение NStorm »

uldemir, да если еще дальше по ссылке пройти, всё объяснено. Но вы ведь разобрались уже как размер стека увеличить. Раз в вашем камне осталась еще память для кучи, значит и стек можно еще увеличивать.
Вы размер карты на этапе компиляции будете ведь знать - так и задавайте там, чтобы в стеке лежало. Динамическое распределение памяти и malloc() выгодны на ПК, где памяти много и процесс может динамически запрашивать и освобождать память. На МК такую роскошь себе позволить нельзя. Надо понимать, что свопа никто не добавит, когда закончится физическая память. Поэтому буфер должен быть максимально такого размера, сколько может быть данных и хватает памяти. Ротацию данных внутри буфера можно и без динамической памяти устроить.
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Вопросы по С/С++ (СИ)

Сообщение uldemir »

Увы и нет. Размер карты выясняется на этапе выполнения (смотреть самый конец сообщения). Но, конечно, я лукавлю. Не нужен мне реально malloc(). Меня интересует метод, как разместить массив в любом месте памяти и с ним комфортно работать. Потому как функция создающая карту использует глобальную переменную для которой статически уже выделена память, затем, эта карта переносится во флеш память для хранения и только потом я из флеш памяти её достаю для отображения. Так что, реально, я могу просто использовать уже выделенный кусок памяти или, хочется научиться использовать данные, которые сохранил во флеш-памяти не вытаскивая оттуда. Ваше предложение создать массив указателей сейчас обдумывается.

Конечно, исходная проблема, как узнать, что размер стека маловат - до сих пор не выяснена. И в той, теме, куда была приведена ссылка, этот вопрос так и не был решен. Была распальцовка, было указание увеличить стек, потом опять распальцовка, а вот как проконтролировать - так и не было сказано. Возможно, это недостаток Кейла, но в нём я так и не нашел репорт, где написано "max stack usage". С другой стороны, если бы Кейл знал это, что ему мешало бы самому выделить под стек необходимую память.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

[uquote="uldemir",url="/forum/viewtopic.php?p=3763803#p3763803"]Возможно, это недостаток Кейла, но в нём я так и не нашел репорт, где написано "max stack usage".[/uquote]--info=stack
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

Всем добрый вечер. Пытаюсь откомпилировать код, найденный на просторах интернета. Сижу в AtmelStudio. Код для МКонтроллера AVR. МКонтроллер Attiny (малолапчатый)
main.cpp
Спойлер

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

#include <avr/io.h>
#include <avr/interrupt.h>
#include "shiftreg.h"
/* macro definition which returns the number of elements in an arraay */
//#define GetArrayElements(x)	sizeof(x)/sizeof(x[0])

/* 7 Segment Codes */
#define ZERO	0x3F
#define ONE	0x06
#define TWO	0x5B
#define THREE	0x4F
#define FOUR	0x66
#define FIVE 	0x6D
#define SIX	0x7D
#define SEVEN	0x07
#define EIGHT	0x7F
#define NINE	0x6F

int main(void)
{
	//unsigned short counter = 0;
	//unsigned char temp;
	//unsigned char digits[] = {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE};
	//unsigned char display[4];
	SHIFTREG_register reg;
	reg = SHIFTREG_InitRegister(&DDRB, &PORTB, PB0, PB1, PB2);
	sei();
    while (1) {  }
}
shiftreg.h
Спойлер

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

/******************************************************************************
* File Name     : shiftreg.h
* Author        : D.Gotic
* Version       : V0.1
* Date          : 03/12/2010
* Description   : This file contains all the functions prototypes 
*                 and structure definitions for the 74HC595 shit register driver
******************************************************************************/
/* Define to prevent recursive inclusion ------------------------------------*/
#ifndef SHIFTREG_H
#define SHIFTREG_H
/* Includes ------------------------------------------------------------------*/
#include <inttypes.h>
/* a structure which defines the interface  from the uC to the SHIFT REGISTER */
typedef struct _SHIFTREG_register
{
volatile uint8_t *DDR_addr;	/* address of the uC Data Direction Register      */
volatile uint8_t *PORT_addr;	/* address of the uC PORT Register                */
         uint8_t DS_pin;		/* Pin number to which the DS pin is connected 	  */
         uint8_t ST_CP_pin;		/* Pin number to which the ST_CP pin is connected */
         uint8_t SH_CP_pin;		/* Pin number to which the SH_CP pin is connected */
} SHIFTREG_register;
/*	Function prototypes -----------------------------------------------------------*/
SHIFTREG_register SHIFTREG_InitRegister(
volatile uint8_t *ddr_addr,
volatile uint8_t *port_addr,
         uint8_t ds_pin,
         uint8_t st_cp_pin,
         uint8_t sh_cp_pin
);

void SHIFTREG_OutputValue(
SHIFTREG_register *reg,
unsigned char *bytes,
unsigned char nbytes
);

#endif	/* SHIFTREG_H */

/************************** END OF FILE **************************/
shiftreg.c
Спойлер

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

/****************************************************************************
* File Name    : shiftreg.c
* Author       : D.Gotic
* Version      : V0.1
* Date         : 03/12/2010
* Description  : This file contains all the functions definitions 
*                      for the 74HC595 shit register driver 
*****************************************************************************/
/* Includes ----------------------------------------------------------------*/
#include "shiftreg.h"
#include "macros.h"

#define BIT_MASK 0x80

/* Private macros-----------------------------------------------------------*/
/* Private functions -------------------------------------------------------*/
#define shift_in_pulse(port,reg_pin)     sbi(port,reg_pin); cbi(port,reg_pin)
#define parallel_out_pulse(port,reg_pin) sbi(port,reg_pin); cbi(port,reg_pin)
//
// Function Name : SHIFTREG_InitRegister
// Description   : Initializes the interface from the uC to the shift register
// Input         : DDR adress and PORT adress of the interface and pin numbers
//                 of the uC interface
// Return        : initialized register structure 
//
SHIFTREG_register SHIFTREG_InitRegister(
volatile uint8_t *ddr_addr,
volatile uint8_t *port_addr,
         uint8_t ds_pin,
         uint8_t st_cp_pin,
         uint8_t sh_cp_pin)
{
	SHIFTREG_register tmp_reg;
	
	tmp_reg.DDR_addr 		= ddr_addr;
	tmp_reg.PORT_addr 		= port_addr;
	tmp_reg.DS_pin			= ds_pin;
	tmp_reg.ST_CP_pin		= st_cp_pin;
	tmp_reg.SH_CP_pin		= sh_cp_pin;
	
	sbi(*(tmp_reg.DDR_addr),tmp_reg.DS_pin);				
	sbi(*(tmp_reg.DDR_addr),tmp_reg.ST_CP_pin);		
	sbi(*(tmp_reg.DDR_addr),tmp_reg.SH_CP_pin);		

	return tmp_reg;
}
/****************************************************
* Function Name  : SHIFTREG_OutputValue
* Description    : Transmits nbytes bytes to nbytes shift registers and outputs 
*		         : the values
* Input          : shift register structure, bytes to transmit, number of bytes
*		         : to transmit
* Return         : None
******************************************************/
void SHIFTREG_OutputValue(
SHIFTREG_register *reg,
unsigned char *bytes,
unsigned char nbytes )
{	
		unsigned char mask, i, j;

		for (i=0; i<nbytes; i++)
		{
			mask = BIT_MASK;

			for (j = 0; j< 8; j++)
			{
				/* mask bit
				 * if bit 0 output 0
				 * else output 1
				 * shift bit mask one place right */
				if (bytes[i] & mask)
				{
					sbi(*(reg->PORT_addr),reg->DS_pin);
					shift_in_pulse(*(reg->PORT_addr),reg->SH_CP_pin);
				}
				else
				{
					cbi(*(reg->PORT_addr),reg->DS_pin);
					shift_in_pulse(*(reg->PORT_addr),reg->SH_CP_pin);
				}
				mask = (mask >> 1);
			}
		}
		parallel_out_pulse(*(reg->PORT_addr),reg->ST_CP_pin);
}
/***********************END OF FILE***********************/
macros.h
Спойлер

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

/*************************************************************************
* File Name   : shiftreg.h
* Author      : D.Gotic
* Version     : V0.1
* Date        : 03/12/2010
* Description : Helper macros for setting and clearing a bit in a register
**************************************************************************/
#ifndef MACROS_H
#define MACROS_H
#define cbi(addr,bit)	addr &= ~(1 << bit)
#define sbi(addr,bit)	addr |= (1 << bit)
#endif	/* MACROS_H */
/****************************END OF FILE**********************************/
В данном случае хочу разобраться в структурах, типах передаваемых данных, ссылках и указателях в аргументах и параметрах функции.
При компиляции в AtmelStudio ошибка:
Error undefined reference to
"SHIFTREG_InitRegister(unsigned char volatile*, unsigned char volatile*, unsigned char, unsigned char, unsigned char)"
Ошибка неопределенной ссылки на ...

Фрагмент кода с прототипом функции

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

/* ----------------- Function prototypes ------------------------------------------------*/
SHIFTREG_register SHIFTREG_InitRegister(volatile uint8_t *ddr_addr, volatile uint8_t *port_addr,uint8_t ds_pin, uint8_t st_cp_pin, uint8_t sh_cp_pin);
В функцию необходимо передать в качестве параметров DDRB, PORTB, PB0, PB1, PB3 (порт и пины к которым подключается регистр 74HC595)
ErrorList.png
ErrorList
(17.29 КБ) 213 скачиваний
Attinu_74HC595.png
(20.23 КБ) 222 скачивания
И что за unsigned char - ясно же сказано uint8_t
Может быть преобразование типов в компиляторе происходит не корректно? :dont_know:
Ссылка -> Подобная ошибка, но машинный перевод
P.S. Аксиома "Код, скачаный из интернета, никогда сразу не работает"
Последний раз редактировалось Эйлер Леонард Сб дек 28, 2019 22:45:29, всего редактировалось 2 раза.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

unsigned char и uint8_t - одно и то же.

undefined reference - функция определена в файле shiftreg.c, а раз такая ошибка - то его, похоже, забыли добавить в список для компиляции.
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

Нет, все файлы подключены.
Файлы проекта ....
2019-12-29_004423.png
(20.08 КБ) 256 скачиваний
Первоначально файл shiftreg был типом .C , а у меня проект как CPP. Изменил тип файла на CPP и вроде бы как скомпилировалось без ошибок.
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Вопросы по С/С++ (СИ)

Сообщение uldemir »

У С и С++ различаются способы подключения хидер-файлов. Я в этом не эксперт, просто сам нарвался, когда хотел править ардуиновский скетч...
Вот пример хидер-файла:

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

#ifdef __cplusplus
extern "C" {
#endif

int sumI(int a, int b);
float sumF(float a, float b);

#ifdef __cplusplus
} // end extern "C"
#endif
Эти ifdef/endif разделяют способ, как компиляторы его будут видеть.
компилятор C:

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

int sumI(int a, int b);
float sumF(float a, float b);
компилятор C++ :

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

extern "C" {

int sumI(int a, int b);
float sumF(float a, float b);

} // end extern "C"
Т.е. main.cpp должен видеть второй вариант.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

ОК! Всё фурычит.
Test-30(1)_74HC595.png
Тестирование 74HC595 (счетчик)
(35.8 КБ) 254 скачивания
Поправил main.cpp
Спойлер

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

#include <avr/io.h>
#include <avr/interrupt.h>
#include "shiftreg.h"
/* macro definition which returns the number of elements in an arraay */
#define GetArrayElements(x)	sizeof(x)/sizeof(x[0])

#define Prescaler_No   (1<<CS00) //No prescaling)
#define Prescaler_8    (1<<CS01)
#define Prescaler_64   (1<<CS01)|(1<<CS00)
#define Prescaler_256  (1<<CS02)
#define Prescaler_1024 (1<<CS00)|(1<<CS02);

/* 7 Segment Codes */
#define ZERO	0x3F
#define ONE		0x06
#define TWO	    0x5B
#define THREE	0x4F
#define FOUR	0x66
#define FIVE 	0x6D
#define SIX		0x7D
#define SEVEN	0x07
#define EIGHT	0x7F
#define NINE	0x6F

volatile uint8_t increment_counter = 0;

ISR(TIM0_COMPA_vect)
{
	cli();
	increment_counter = 1;
	sei();
}

int main(void)
{	
	unsigned short counter = 0;
	unsigned char temp;
	unsigned char digits[] = {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE};
	unsigned char display[4];
	
	SHIFTREG_register reg;
	
	TCNT0 = 0; //Очищаем счетный регистр (на ваякий случай)
	OCR0A = (256-1)-0;//Регистр сравнения, (256-1)-число
	TCCR0A = (1<<WGM01);// Сброс при совпадении.
	TIFR0 = (1<<OCF0A); // Регистр флагов прерываний таймера счетчика
	TIMSK0 = (1<<OCIE0A); //Разрешение прерывания по совпадению таймера/счётчика 0A
	TCCR0B = Prescaler_No;// Делитель частоты
//	                                           ds_pin,st_cp_pin,sh_cp_pin
	reg = SHIFTREG_InitRegister(&DDRB, &PORTB, PB0,   PB1,      PB2);
	sei();
    while (1) {
		
if(increment_counter)
{
++counter;
if(counter > 9999){	counter = 0; }
increment_counter = 0;
}
		temp	   =  counter / 1000;
		display[0] =  digits[temp];
		temp	   =  (counter / 100) % 10;
		display[1] =  digits[temp];
		temp	   =  (counter / 10)  % 10;
		display[2] =  digits[temp];
		temp	   =  counter % 10;
		display[3] =  digits[temp];	
	
	SHIFTREG_OutputValue(&reg,display,GetArrayElements(display));
	}
return 0;
}
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Мне думается, что, cli() и sei() внутри ISR - лишнее.
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

Вот, вот! Существуют разные мнения на сей счет. Остановка прерывания внутри прерывания. Типа того "а вдруг бы чего не вышло не того". Ко мне давно подкрадывался этот вопрос. И, все таки я так же считаю cli() и sei() внутри ISR - лишними. К тому же где то находил убедительные разъяснения по этому поводу.
Я называю это "Копипастинг кусает за пятки". :))
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

cli() внутри ISR, вероятнее всего лишнее, а вот sei() может быть оправдано.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=3765069#p3765069"]а вот sei() может быть оправдано.[/uquote]А можно узнать, как тогда вы попадаете в прерывание, если они у вас были запрещены? :dont_know:
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

VladislavS писал(а):А можно узнать, как тогда вы попадаете в прерывание, если они у вас были запрещены?
любознательность - это очень похвально! :)
в обработчик прерывания я попадаю уже при запрещенных прерываниях, хотя до момента установки флага запроса прерывания они были разрешены
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Starichok51
Модератор
Сообщения: 19045
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Starichok51 »

ARV писал(а):а вот sei() может быть оправдано.
такое может понадобиться, если есть необходимость, чтобы другое прерывание (более важное) могло прервать ход выполняемого прерывания.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

Частный случай;

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

ISR(INT0_vect)//External Interrupt
{
   ips++;//На порт PB2 подаем импульсы  _П_П_П_П_П_
}; 
ISR(TIM0_COMPA_vect)//прерывание по совпадению
{   
MAX7219_display_number(ips);//выводим на дисплей цифры  
   ips=0;
};
С внешнего прерывания считаем (инкрементируем) импульсы. Далее, через определенный период тиков, установленных в таймере-компараторе, подаем их на цифровой дисплей, обнуляем инкремент. Сначала я тренировался на чипе MAX7219, но и с 74HC595 так же считаю необходимым подружиться. А в ISR(TIM0_COMPA_vect){ /* необходимо добавить немного if-ов для усреднения значений */}. Ну и какое из прерываний кого хочет перебороть? Да вроде бы всё мирно должно быть.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=3765088#p3765088"]в обработчик прерывания я попадаю уже при запрещенных прерываниях, хотя до момента установки флага запроса прерывания они были разрешены[/uquote]Уже начал забывать это как страшный сон :)
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

-->приоритет прерываний AVR. Пока для меня этот вопрос не столь актуален. Если что, подкуюсь теорией и Гугли. :))
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Внутри ISR() прерывания запрещены и так, так что cli() не нужен. Равно как и sei() в конце - после выхода из обработчика прерывания и без этого включатся.

А вот если нужно неблокирующее прерывание (так, чтобы другие были разрешены), есть ISR_NOBLOCK:

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

ISR(TIM0_COMPA_vect, ISR_NOBLOCK)
avr-libc обо всём позаботится.
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Re: Вопросы по С/С++ (СИ)

Сообщение Эйлер Леонард »

Есть такое дело.
ISR_NOBLOCK.png
ISR_NOBLOCK в interrupt.h
(15.02 КБ) 218 скачиваний
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

ISR_NOBLOCK не совсем то же самое, что и sei() внутри обработчика. все дело в моменте разрешения прерываний: макрос делает это сразу после входа, а самодобавленный sei() - когда надо программисту.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

Вернуться в «Разные вопросы по МК»