Не проще ли пересмотреть структуру программы - массив или индексный переход?Есть у меня switch case состоящая из 10 case и таких конструкций несколько
Вопросы по С/С++ (СИ)
- Реклама
Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны (при отсутствии default, конечно). Тоже какой-никакой контроль.
только при условии, что тип переменной в switch соответствует enumWiseLord писал(а):Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 574
- Зарегистрирован: Вт ноя 02, 2010 17:46:37
А можно по подробнее ?Не проще ли пересмотреть структуру программы - массив или индексный переход?
Это я делаю протокол I2C Без delay_us
при переходе с одного case на другое выполнится автоматически задержка.
пока сделал до ASK
примерно это выглядит так.
Спойлер
Код: Выделить всё
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
switch(t1){
case EXIT:{break;} // Передачик выключен
//------------START--------------------
case START:{
SDA_1
SCL_1
t1=START_1;
break;
}
case START_1:{
SDA_0
t1=START_1;
break;
}
case START_2:{
SCL_0
t1=SEND;
break;
}
//------------Send--------------------
case SEND:{
//---------- даные data
flag_I2C=data&0x80;
data=data<<1;
//---------- данные пуст ?
if(data==0){
t1=ASK;
}
else{
t1=SEND_1;
}
//-----------выставляем bit0 на линию------
if(flag_I2C==0x80){
SDA_1
}
else{
SDA_0
}
break;
}
case SEND_1:{
SCL_1
t1=SEND_2;
break;
}
case SEND_2:{
SCL_0
t1=SEND; // циклически передаём данные
break;
}
//------------ASK--------------------
case ASK:{
////////////////////////////////////SDA=IN
t1=ASK_1;
break;
}
case ASK_1:{
SCL_1
if(SDA==0){
t1=ASK_2; // идём дальше
}
else{
//ошибка
}
break;
}
case ASK_2:{
SCL_0
t1=ASK_3;
break;
}
case ASK_3:{
if(SDA==1){
//t1=ASK_2 // идём дальше добавить суловия куда идти
//SDA=out
}
else{
//ошибка
}
break;
}
//------------STOP--------------------
case STOP:{
SDA_0
SCL_1
t1=STOP_1;
break;
}
case STOP_1:{
SDA_1
t1=EXIT;
break;
}
}
TCNT2=DELAYX;
TCNT2=0xFA;
}
Там вариантов много. Например можно использовать массив указателей на функции, если параметры в CASE у вас идут по порядку. Либо алгоритмы работы со списками, и прочее.pokk писал(а):А можно по подробнее ?
Конкретно как сейчас вам лучше организовать - не готов ответить.
- Реклама
pokk, у вас на метку START_2 код никогда не попадет) поправьте обработчик START_1.
а так все ок.
я бы писал так:
а так все ок.
я бы писал так:
Код: Выделить всё
typedef enum{
START = 0,
START_1,
START_2,
START_3,
....
} mode_t;
mode_t Mode;
interrupt [TIM2_OVF] void timer2_ovf_isr(void) {
TCNT2=DELAYX; // это в самом начале обработчика, чтобы задержка не зависела от времени выполнения switch-case
switch(Mode){
case START:
....
break;
case START_1:
....
break;
default:
....
break;
}
}Ставим плюсы: )
- Сообщения: 574
- Зарегистрирован: Вт ноя 02, 2010 17:46:37
что-то не понял как задержка зависит swith-case? задал частоту 100 Khz и всё главное что бы в прерывание успело выполнится за данный период.ibiza11 писал(а):TCNT2=DELAYX; // это в самом начале обработчика, чтобы задержка не зависела от времени выполнения switch-case
а где задавать частоту какая разница в любом же случает он выполнит всё прерывание.
Я вообще специально вниз поставил что бы можно было изменить задержку.
типа так:
Код: Выделить всё
interrupt [TIM2_OVF] void timer2_ovf_isr(void) {
switch(Mode){
case START:
DELAYX=5 мк
....
break;
case START_1:
....
break;
case STOP:
DELAYX=255 мк
break;
default:
....
break;
}
TCNT2=DELAYX;
}сделал как предложил ibiza11 пару case закомментировал и нечего от CodeVision не увидел.WiseLord писал(а):Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны (при отсутствии default, конечно). Тоже какой-никакой контроль.
прерывание таймера происходит по его переполнению. т.е. значение TCNT2 в этот момент = 0.pokk писал(а):что-то не понял как задержка зависит swith-case?
После входа в прерывание, таймер не останавливается, и, в зависимости от предделителя таймера, может насчитать еще несколько импульсов во время выполнения обработчика прерывания.
Операция TCNT2=DELAYX; предназначена для того, чтобы сместить начальное значение TCNT2 относительно нуля, тем самым определяя кол-во тиков таймера до момента его прерывания.
Для примера: TCNT2 = 100 - определит задержку равную (256-100)=156 тикам таймера при условии, что в начальный момент значение таймера = 0, поскольку таймер (в данном случае таймер №2) переполнится после значения 255.
Но, поскольку эта операция может быть произведена в момент, когда значение TCNT2 не равно нулю, может появиться погрешность в бОльшую сторону равная значению TCNT2 в момент совершения операции присвоения. Поэтому, чем раньше вы ее произведете, тем меньше вероятность того, что возникнет погрешность.
У любой инструкции есть время выполнения, а поскольку switch-case также является инструкцией контроллера, то и у нее есть время выполнения. Следовательно пока выполняется switch-case значение таймера может стать отличным от нуля.
Все это можно проверить в симуляторе или попытаться рассчитать, имея значение предделителя таймера.
Ставим плюсы: )
- Сообщения: 574
- Зарегистрирован: Вт ноя 02, 2010 17:46:37
Благодарю за помощь.
Я упустил момент, что таймер не останавливается после входа в прерывание.
Я упустил момент, что таймер не останавливается после входа в прерывание.
А как описать, что мне нужен массив из 11 таких элементов:
Вернее, у меня есть такой массив: volatile unsigned int videobuff[11], но мне хочется, чтобы когда я переписываю младший байт - старший не менялся бы. Вернее я мог бы решать, что хочу переписать: младший байт, старший или только один бит установить/сбросить.
Код: Выделить всё
struct {
unsigned char image : 8;
unsigned char brightness : 3;
unsigned char blink : 1;
}symbol;ну, в подобных случаях я поступаю так:
Код: Выделить всё
typedef struct {
unsigned char image : 8;
unsigned char brightness : 3;
unsigned char blink : 1;
}symbol_t;
symbol_t videobuf[11];
// доступ:
vodeobuf[5].blink = 0;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 70
- Зарегистрирован: Пт янв 31, 2014 17:08:09
Доброго времени суток. Хочу научится программировать, с чего начать? 
С компа, на МК сразу писать смысла особого нет 
http://lib.ru/CTOTOR/starterkit.txt
На название внимания не обращайте, книга действительно хорошая для начинающих.
http://lib.ru/CTOTOR/starterkit.txt
На название внимания не обращайте, книга действительно хорошая для начинающих.
Товарищи коты, помогите пожалуйста. Есть функция, в которую я должен передать n-й элемент массива. Пытаюсь передать через указатель. Передаваемый элемент функция вроде бы видит, но увеличивать адрес указателя у меня не получается. Пробовал по-разному, это один из вариантов. Подскажите пожалуйста, как правильно
Код: Выделить всё
static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len)
{
while (M95_read_SR() & M95_WIP);
M95_CS_0();
SPI1_write_byte(M95_WREN);
M95_CS_1();
while (M95_read_SR() & M95_WIP);
while ((M95_read_SR() & M95_WEL) == 0);
M95_CS_0();
SPI1_write_byte(M95_WRITE);
SPI1_write_byte((addr >> 8) & 0xFF);
SPI1_write_byte(addr & 0xFF);
for (uint8_t i = 0; i < len; i++) {
SPI1_write_byte(buffer);
(*buffer)++;
}
M95_CS_1();
while (M95_read_SR() & M95_WIP);
}Осилит дорогу идущий
--------------------------
Пишу на Си за еду
--------------------------
Пишу на Си за еду
указатель сдвигается так:
Код: Выделить всё
buffer++;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
я пробовал так:
но тогда получается, что я увеличиваю не адрес, а значение первого элемента buffer. т.е. если передаю в функцию массив buff[] = {AA, 00, 00, 00....}, на выходе из этой функции у меня выходит {AA, AB, AC, AD....}
если делаю так:
то на выходе у меня совсем мусор выходит. а в предыдущем случае хоть первый элемент ловило
Код: Выделить всё
for (uint8_t i = 0; i < len; i++) {
SPI1_write_byte(buffer);
buffer++;
}если делаю так:
Код: Выделить всё
for (uint8_t i = 0; i < len; i++) {
SPI1_write_byte(*buffer);
buffer++;
}Осилит дорогу идущий
--------------------------
Пишу на Си за еду
--------------------------
Пишу на Си за еду
как определена эта функция: SPI1_write_byte(buffer);? я так понимаю, именно она отправляет ваши байты? может, вы неправильно ей параметр передаете, потому что между SPI1_write_byte(buffer); и SPI1_write_byte(*buffer); большая разница: вы пробовали и так и этак - разве компилятор не варнингует у вас?!
да и каким образом вы массив передаете в эту функцию: static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len) - может, проблема еще "выше"?
что касается указателя, то в вашем случае:
buffer++ - инкремент УКАЗАТЕЛЯ
*buffer++ - инкремент указателя
(*buffer)++ инкремент ПО УКАЗАТЕЛЮ, т.е. элемента массива
да и каким образом вы массив передаете в эту функцию: static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len) - может, проблема еще "выше"?
что касается указателя, то в вашем случае:
buffer++ - инкремент УКАЗАТЕЛЯ
*buffer++ - инкремент указателя
(*buffer)++ инкремент ПО УКАЗАТЕЛЮ, т.е. элемента массива
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
функция передачи по SPI:
пробовал делать так:
тоже мешанина на выходе.
функцию M95_write(...) я вызываю так:
Код: Выделить всё
void SPI1_write_byte(uint8_t b)
{
uint8_t temp;
SPI_I2S_SendData(SPI1, b);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
temp = SPI_I2S_ReceiveData(SPI1);
}Код: Выделить всё
uint8_t temp1 = *buffer;
SPI1_write_byte (temp1);
функцию M95_write(...) я вызываю так:
Код: Выделить всё
for (uint8_t i = 0; i < 8; i++) {
M95_write(DIS_PAGE_START + (32 * i), (APP_Tx_Buffer[4 + (32 * i)]), 32);
}Осилит дорогу идущий
--------------------------
Пишу на Си за еду
--------------------------
Пишу на Си за еду
функция определена как static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len), то есть второй параметр - УКАЗАТЕЛЬ НА БАЙТ
вызываете вы ее так:M95_write(DIS_PAGE_START + (32 * i), (APP_Tx_Buffer[4 + (32 * i)]), 32); то есть вторым параметром передаете ей БАЙТ
варнинг компилятора есть на вызов функции? должен быть бы по идее...
правильно вызывать так:M95_write(DIS_PAGE_START + (32 * i), &APP_Tx_Buffer[4 + (32 * i)], 32);
ну а затем в теле функции уже так:или так:
вызываете вы ее так:M95_write(DIS_PAGE_START + (32 * i), (APP_Tx_Buffer[4 + (32 * i)]), 32); то есть вторым параметром передаете ей БАЙТ
варнинг компилятора есть на вызов функции? должен быть бы по идее...
правильно вызывать так:M95_write(DIS_PAGE_START + (32 * i), &APP_Tx_Buffer[4 + (32 * i)], 32);
ну а затем в теле функции уже так:
Код: Выделить всё
for (uint8_t i = 0; i < len; i++) {
SPI1_write_byte(*buffer++);
}Код: Выделить всё
for (uint8_t i = 0; i < len; i++) {
SPI1_write_byte(buffer[i]);
}если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Точно:) спасибо большое!
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
--------------------------
Пишу на Си за еду


