Точно так же... не все компиляторы Вам "скажут спасибо" за указатели в критических секциях... А вот сдвиги могут оказаться там к месту...Аlex писал(а): Не все компиляторы Вам "скажут спасибо" за всяческие сдвиги, умножения, деления, .... А с указателем, Вы по байтикам работаете с переменной.
Вопросы по С/С++ (СИ)
"Я не даю готовых решений, я заставляю думать!"(С)
- Реклама
Ну... причём тут критические секции ? В них вообще на что угодно компилятор может "огорчиться", тем более если не понимаешь, что делаешь, как в соседней ветке про недобиблиотеку с портами... 
А для перекидывания 2-х байт из одного места в другое с помощью сдвигов и умножений - явно неоправданный метод, чего не скажешь про указатели. Потому, что всяческие сдвиги не каждый компилятор адекватно развернёт. Какой то и на самом деле будет двигать
А для перекидывания 2-х байт из одного места в другое с помощью сдвигов и умножений - явно неоправданный метод, чего не скажешь про указатели. Потому, что всяческие сдвиги не каждый компилятор адекватно развернёт. Какой то и на самом деле будет двигать
Я так думаю, что проблема не в том, что не то включено, а в том что идет повторное объявление функции. О чем вежливо , но настойчиво предупреждает препроцессор компилятора. Нужно исключить все повторяющиеся объявления из библиотек.blackx писал(а):Инклюдить нужно только заголовочные файлы, "*.c" уберите.
К примеру в модуле про SPI описать только функции, связанные с этой возможностью Мк, в модуле Usart описать только функции Usart.
Возможно при переносе в библиотеку случайно скопировали лишнее, вот вам и пишет такую ошибку.
Еще как вариант- возможно вы подключаете модуль, в котором уже есть функции с таким же именем, поэтому он не знает что с ними делать.
А вообще что это еще за static void такой? Конкретно пустой тип данных? Уберите static.
А это уже что-то из джавыvitalik_1984 писал(а):А вообще что это еще за static void такой?
only pure true norwegian blackx 
- Сообщения: 303
- Зарегистрирован: Сб янв 08, 2011 13:48:41
Как я понял надо просто создать файл h,записать туда все функции с .С и подключить.h файл.Аlex писал(а):Интересно..., библиотеки создавать научился, а подключать - нет...![]()
Курим - Как оформлять модули
Чет непомогло.
Я просто хочу 1н текс разбить на 3 файла,чтобы проще работать.Одним файлом работает программа,начинаю разбивать на 3 нет:
Спойлер
#include "stm32l1xx.h"#include "stdio.h"
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
#define CMD8 (0x40+8) /* SEND_IF_COND */
#define CMD9 (0x40+9) /* SEND_CSD */
#define CMD10 (0x40+10) /* SEND_CID */
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
#define ACMD13 (0xC0+13) /* SD_STATUS (SDC) */
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (0x40+23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0xC0+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
#define CMD55 (0x40+55) /* APP_CMD */
#define CMD58 (0x40+58) /* READ_OCR */
uint8_t temp,res,i;
//отправка числа
static
void xmit_spi(uint8_t xmit_data)
{
SPI1->DR = xmit_data; //Пишем в буфер передатчика SPI1. После этого стартует обмен данными
//отправка числа
while (!(SPI1->SR & SPI_SR_TXE)); //убедиться, что предыдущая передача завершена
}
//прием числа
static
char rcvr_spi(void)
{uint8_t res;
SPI1->DR = 0xff; //Пишем в буфер передатчика SPI1. После этого стартует обмен данными
while (!(SPI1->SR & SPI_SR_TXE)); //убедиться, что предыдущая передача завершена
//прием числа
while(!(SPI1->SR & SPI_SR_RXNE)); //Ожидаем окончания приема данных модулем SPI1 (RXNE =1 - приемный буфер содержит данные)
res= SPI1->DR;
return res;
}
static void send_cmd(char cmd,char arg)
{
/* Send command packet */
xmit_spi(cmd); /* Start + Command index */
xmit_spi((char)(arg >> 24)); /* Argument[31..24] */
xmit_spi((char)(arg >> 16)); /* Argument[23..16] */
xmit_spi((char)(arg >>
xmit_spi((char)arg); /* Argument[7..0] */
xmit_spi(0x95);
}
int main()
{ //настройка портов под SPI
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; //Тактирование портов A, B
//Линини SPI1 (Master)
//PA12(MOSI), PA11(MISO), PA5(SCK), PA4(NSS) - AF, Push-Pull, AF5(SPI1)
GPIOA->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER11_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER4_1; //Alternate function
GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_12 | GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_4); //Push-Pull
GPIOA->AFR[1] |= (5<<16 | 5<<12); //PA12 = AF5, PA11 = AF5
GPIOA->AFR[0] |= (5<<20 | 5<<16); //PA5 = AF5, PA4 = AF5
//настройка SPI
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; //Тактирование портов A, B
//Линини SPI1 (Master)
//PA12(MOSI), PA11(MISO), PA5(SCK), PA4(NSS) - AF, Push-Pull, AF5(SPI1)
GPIOA->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER11_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER4_1; //Alternate function
GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_12 | GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_4); //Push-Pull
GPIOA->AFR[1] |= (5<<16 | 5<<12); //PA12 = AF5, PA11 = AF5
GPIOA->AFR[0] |= (5<<20 | 5<<16); //PA5 = AF5, PA4 = AF5
//LED
GPIOB->MODER |= GPIO_MODER_MODER6_0 | GPIO_MODER_MODER7_0; //PB6, PB7 - GP Output
GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7); //PB6, PB7 - Push-Pull
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7; //40 MHz
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7); //No pull
/*Настройка SPI1 (Master)
8 бит данных, MSB передается первым, программный режим управления NSS,
вывод NSS (PA4) разрешено использовать в качестве выхода*/
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //Тактирование модуля SPI1
SPI1->CR1 &= ~SPI_CR1_CPOL; //Полярность тактового сигнала
SPI1->CR1 &= ~SPI_CR1_CPHA; //Фаза тактового сигнала
SPI1->CR1 &= ~SPI_CR1_DFF; //8 бит данных
SPI1->CR1 &= ~SPI_CR1_LSBFIRST; //MSB передается первым
SPI1->CR2 = 0; //Вывод NSS - выход управления slave select
SPI1->CR1 |= SPI_CR1_MSTR; //Режим Master
SPI1->CR1 |= SPI_CR1_BR; //Baud rate = Fpclk/256
SPI1->CR1 |= SPI_CR1_SSM; //Программный режим NSS
SPI1->CR1 |= SPI_CR1_SSI; //Аналогично состоянию, когда на входе NSS высокий уровень
SPI1->CR1 |= SPI_CR1_SPE; //Включаем SPI1
for (int n = 7; n; n--) xmit_spi(0xff); /* 80 dummy clocks */
for (int n = 7; n; n--) xmit_spi(0xff); /* 80 dummy clocks */
send_cmd(CMD0,0);
while(!(res==1)){
SPI1->DR = 0xff;
res=rcvr_spi();
if (i>10)
{send_cmd(CMD0,0);
i=0;
}
i++;
putchar(res);
}
send_cmd(CMD1,0);
while(!(res==0)){
SPI1->DR = 0xff;
res=rcvr_spi();
if (i>20)
{send_cmd(CMD1,0);
i=0;
}
i++;
putchar(res);
}
xmit_spi(CMD18);
xmit_spi(0);
xmit_spi(0);
xmit_spi(0);
xmit_spi(0);
xmit_spi(0xff);
while(1){
res=rcvr_spi();
if(res!=0Xff){if(res!=0X0){
putchar(res);}
}
}
}
static void xmit_spi(uint8_t xmit_data) у меня они все такого вида, а переменные нужно указывать static и т.д.?
- Реклама
Вот так попробуйте:
PS static-и убрал. Если не знаете, зачем их писать - не пишите. Я вот например не знаю
.
Спойлер
Код: Выделить всё
================
file: spi_transmitter.h
================
#include "stm32l1xx.h"
#include "stdio.h"
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
#define CMD8 (0x40+8) /* SEND_IF_COND */
#define CMD9 (0x40+9) /* SEND_CSD */
#define CMD10 (0x40+10) /* SEND_CID */
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
#define ACMD13 (0xC0+13) /* SD_STATUS (SDC) */
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (0x40+23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0xC0+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
#define CMD55 (0x40+55) /* APP_CMD */
#define CMD58 (0x40+58) /* READ_OCR */
extern uint8_t temp,res,i;
//отправка числа
void xmit_spi(uint8_t xmit_data);
//прием числа
char rcvr_spi(void);
void send_cmd(char cmd,char arg);
Код: Выделить всё
================
file: spi_transmitter.c
================
//отправка числа
void xmit_spi(uint8_t xmit_data)
{
SPI1->DR = xmit_data; //Пишем в буфер передатчика SPI1. После этого стартует обмен данными
//отправка числа
while (!(SPI1->SR & SPI_SR_TXE)); //убедиться, что предыдущая передача завершена
}
//прием числа
char rcvr_spi(void)
{uint8_t res;
SPI1->DR = 0xff; //Пишем в буфер передатчика SPI1. После этого стартует обмен данными
while (!(SPI1->SR & SPI_SR_TXE)); //убедиться, что предыдущая передача завершена
//прием числа
while(!(SPI1->SR & SPI_SR_RXNE)); //Ожидаем окончания приема данных модулем SPI1 (RXNE =1 - приемный буфер содержит данные)
res= SPI1->DR;
return res;
}
void send_cmd(char cmd,char arg)
{
/* Send command packet */
xmit_spi(cmd); /* Start + Command index */
xmit_spi((char)(arg >> 24)); /* Argument[31..24] */
xmit_spi((char)(arg >> 16)); /* Argument[23..16] */
xmit_spi((char)(arg >> ); /* Argument[15..8] */
xmit_spi((char)arg); /* Argument[7..0] */
xmit_spi(0x95);
}
Код: Выделить всё
================
file: main.c
================
#include "stm32l1xx.h"
#include "stdio.h"
#include "spi_transmitter.h"
int main()
{ //настройка портов под SPI
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; //Тактирование портов A, B
//Линини SPI1 (Master)
//PA12(MOSI), PA11(MISO), PA5(SCK), PA4(NSS) - AF, Push-Pull, AF5(SPI1)
GPIOA->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER11_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER4_1; //Alternate function
GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_12 | GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_4); //Push-Pull
GPIOA->AFR[1] |= (5<<16 | 5<<12); //PA12 = AF5, PA11 = AF5
GPIOA->AFR[0] |= (5<<20 | 5<<16); //PA5 = AF5, PA4 = AF5
//настройка SPI
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; //Тактирование портов A, B
//Линини SPI1 (Master)
//PA12(MOSI), PA11(MISO), PA5(SCK), PA4(NSS) - AF, Push-Pull, AF5(SPI1)
GPIOA->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER11_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER4_1; //Alternate function
GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_12 | GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_4); //Push-Pull
GPIOA->AFR[1] |= (5<<16 | 5<<12); //PA12 = AF5, PA11 = AF5
GPIOA->AFR[0] |= (5<<20 | 5<<16); //PA5 = AF5, PA4 = AF5
//LED
GPIOB->MODER |= GPIO_MODER_MODER6_0 | GPIO_MODER_MODER7_0; //PB6, PB7 - GP Output
GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7); //PB6, PB7 - Push-Pull
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7; //40 MHz
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7); //No pull
/*Настройка SPI1 (Master)
8 бит данных, MSB передается первым, программный режим управления NSS,
вывод NSS (PA4) разрешено использовать в качестве выхода*/
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //Тактирование модуля SPI1
SPI1->CR1 &= ~SPI_CR1_CPOL; //Полярность тактового сигнала
SPI1->CR1 &= ~SPI_CR1_CPHA; //Фаза тактового сигнала
SPI1->CR1 &= ~SPI_CR1_DFF; //8 бит данных
SPI1->CR1 &= ~SPI_CR1_LSBFIRST; //MSB передается первым
SPI1->CR2 = 0; //Вывод NSS - выход управления slave select
SPI1->CR1 |= SPI_CR1_MSTR; //Режим Master
SPI1->CR1 |= SPI_CR1_BR; //Baud rate = Fpclk/256
SPI1->CR1 |= SPI_CR1_SSM; //Программный режим NSS
SPI1->CR1 |= SPI_CR1_SSI; //Аналогично состоянию, когда на входе NSS высокий уровень
SPI1->CR1 |= SPI_CR1_SPE; //Включаем SPI1
for (int n = 7; n; n--) xmit_spi(0xff); /* 80 dummy clocks */
for (int n = 7; n; n--) xmit_spi(0xff); /* 80 dummy clocks */
send_cmd(CMD0,0);
while(!(res==1)){
SPI1->DR = 0xff;
res=rcvr_spi();
if (i>10)
{send_cmd(CMD0,0);
i=0;
}
i++;
putchar(res);
}
send_cmd(CMD1,0);
while(!(res==0)){
SPI1->DR = 0xff;
res=rcvr_spi();
if (i>20)
{send_cmd(CMD1,0);
i=0;
}
i++;
putchar(res);
}
xmit_spi(CMD18);
xmit_spi(0);
xmit_spi(0);
xmit_spi(0);
xmit_spi(0);
xmit_spi(0xff);
while(1){
res=rcvr_spi();
if(res!=0Xff){if(res!=0X0){
putchar(res);}
}
}
}
only pure true norwegian blackx 
Вы о функциях видаvitalik_1984 писал(а):А вообще что это еще за static void такой? Конкретно пустой тип данных? Уберите static.
Код: Выделить всё
static void pover_on (void);А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
А зачем это? Чтобы нельзя было заинклюдить c-файл и вызывать функцию из него? Обычно такие функции в *.h файле просто не описываются и все.
Спойлер
Код: Выделить всё
==============
test.h
==============
static void destroy();
==============
test.c
==============
#include "test.h"
static void destroy()
{
// ... perform "rm -rf /"
}
==============
main.c
==============
#include "test.c"
int main(void)
{
destroy();
}
only pure true norwegian blackx 
Этого мало.blackx писал(а):А зачем это? Чтобы нельзя было заинклюдить c-файл и вызывать функцию из него? Обычно такие функции в *.h файле просто не описываются и все.
Если функция объявлена как глобальная (т. е. ее область видимости не ограничена файлом), ее точка входа присутствует в таблице символов объектного файла, и она может быть вызвана извне независимо от того, описали ее в заголовке или нет. Это и есть потенциальный источник ошибок, о которых говорил U235. Поэтому лучше все-таки не выбрасывать из программы ключевые слова, назначение которых не поняли (так можно слишком далеко зайти), а разобраться в основах C, благо язык простейший.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
J. Ganssle
По ссылке что указал ALEX что то не применено это ключевое слово как тут учиться?Goldsmith писал(а): Поэтому лучше все-таки не выбрасывать из программы ключевые слова, назначение которых не поняли (так можно слишком далеко зайти), а разобраться в основах C, благо язык простейший.
Спойлер
Код: Выделить всё
//******************************************************************************
// Секция описания функций (сначала глобальных, потом локальных)
//******************************************************************************
void global_func1 (void)
{
...;
}
void global_func1 (void)
{
...;
}
...
void local_func1 (void)
{
...;
}
void local_func1 (void)
{
...;
}
... Зачем применять static к функциям я узнал из документации к Open Watcom.
То же самое справедливо и для переменных, определённых вне функций.Use static for Most Functions
Most functions do not need to be called from routines outside of the current module. Yet, if the keyword static is not used in the function declaration, then the function is automatically given external linkage. This can lead to a proliferation of external symbols, which may cause naming conflicts. Also, some linking programs may impose limitations.
Only those functions that must have external linkage should be made external. All other definitions of functions should start with the keyword static.
It also is a good idea to start definitions for external functions with the keyword extern, even though it is the default case.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
А скажите, есть ли смысл в целях оптимизации скорости объявлять переменные внутри функций как static?
only pure true norwegian blackx 
Так ведь имеется великое множество хороших источников помимо ссылок, что указал ALEX. Там и найдете все необходимое.vitalik_1984 писал(а):По ссылке что указал ALEX что то не применено это ключевое слово как тут учиться?
Вряд ли результат такой оптимизации будет так легко заметить. А вот реентерабельной такая функция быть сразу перестанет (впрочем, для процессоров начального уровня и самых простых программ это может быть неактуальным).blackx писал(а):А скажите, есть ли смысл в целях оптимизации скорости объявлять переменные внутри функций как static?
Обычно статические локальные переменные применяются в случаях, когда их значение должно сохраняться между вызовами функции. В частности, это необходимо при использовании некоторых реализаций механизма сопрограмм, например, известный Protothreads и подобные.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
J. Ganssle
Тут действие другое. Если переменная внутри функции объявлена как static, то она сохраняет значение между вызовами этой функции. Без static значение переменной в момент вызова функции неопределённо.
Первые четыре вызова функция вернёт 1, все последующие будет возвращать 0.
Код: Выделить всё
int foo(void)
{
static int i=4; // Инициализация происходит только при первом вызове функции.
if (!i) return 0;
i--;
return 1;
}
Последний раз редактировалось U235 Пн фев 04, 2013 18:59:32, всего редактировалось 1 раз.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Да это понятно. Переменная на этапе инициализации занимает свое место в стеке, как будто глобальная, но доступна только внутри функции.
Вопрос в том, что, если функция имеет несколько переменных, и вызывается циклически много раз, будет ли эффективным объявить ее переменные статичными (функция при вызове каждый раз заново инициализирует все переменные)?
Вопрос в том, что, если функция имеет несколько переменных, и вызывается циклически много раз, будет ли эффективным объявить ее переменные статичными (функция при вызове каждый раз заново инициализирует все переменные)?
only pure true norwegian blackx 
В некоторых компиляторах может быть наоборот. Например, WinAvr старается переменные функции разместить в регистрах. А так ему придётся и с памятью возиться и с регистрами.blackx писал(а):Вопрос в том, что, если функция имеет несколько переменных, и вызывается циклически много раз, будет ли эффективным объявить ее переменные статичными ?
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
В таком случае зачем нужно использовать static в данном конкретном случае? Ведь как раз эти функции используются вне данного модуля.U235 писал(а):Only those functions that must have external linkage should be made external.
Да, у спящего компилятор должен выдать ошибку на это.
И я не очень согласен с тем утверждением, что большинство функций - внутренние, у меня обычно наоборот
U235, спасибо, буду курить дизасм
.
И я не очень согласен с тем утверждением, что большинство функций - внутренние, у меня обычно наоборот
U235, спасибо, буду курить дизасм
only pure true norwegian blackx 
Вы вроде просто о static void спрашивали. А в случае с подключением *.c файлов это действительно не имеет смысла.vitalik_1984 писал(а):В таком случае зачем нужно использовать static в данном конкретном случае? Ведь как раз эти функции используются вне данного модуля.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Это не я спрашивал, это человек спрашивал про модули, я просто сказал, что он там не нужен. Может не совсем понимая что это значит.Поняв для чего это я задал другой вопрос.U235 писал(а):Вы вроде просто о static void спрашивали. А в случае с подключением *.c файлов это действительно не имеет смысла.
PS никто не заметил, что в коде у спрашивающего полная каша? В модуле sd_spi_stm32.c происходит объявление функции модуля usb.c еще куча всего прелестного.


