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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Сообщение DruidCat »

Народ, а есть уже написанная кем нибуть библиотека на С++ для RS-232? Начал изучать С++ на windows в консоле, охота побыстрее применить уже полученные знания по С++, чтоб управлять МК. А как в консоле на С++ работать с RS-232 не знаю. Если кто знает, дайте ссылочку на готовую библиотеку или на материал учебный, чтоб самому сделать свою библиотеку.
Кот должен прожить жизнь без сожаления.
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

я уже давно пользуюсь этим
http://www.codeforge.cn/read/22611/SerialPort.cpp__html
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Сообщение DruidCat »

urry писал(а):я уже давно пользуюсь этим
http://www.codeforge.cn/read/22611/SerialPort.cpp__html
Спасибо urry, а как собрать этот исходник? Я установи себе Visual Studio 2012(professional) на Windows 8 x64. Скачал на сайте http://www.naughter.com/serialport.html полностью проект, загрузил его через студию 2012, студия его загружала в себя выдавая сообщения о том, что проект состоит в системе управления версиями. А когда я решил скомпиллировать код, выдал ошибку в библиотеке <altwinverapi.h> на строке:

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

#if _WIN32_WINNT < 0x0403
#error This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended. <- ТУТ ОШИБКА
#endif
У меня крайне скромные познания в С++ и я даже не могу проанализировать код. Как мне собрать этот проект? Получается, что студия 2012 не соберет его?
Кот должен прожить жизнь без сожаления.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Это - версия винды и версия эксплорера, естественно, все старое. Незачем это собирать - вас в проекте интересует 2 файла - serialport.cpp serialport.h.
Скопируйте оттуда в свой консольный проект и появится класс CSerialPort. Дальше - как обычно,
CSerialPort port;
port.Open(
и так далее.
Не знаю, как это заработает на винде 8 - проверял только на хп и семерке, кстати, только на 32 битной...
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Сообщение DruidCat »

Спасибо за совет.
Создал консольный проект, с пометкой добавить общие файлы заголовка для библиотек MFC. Заинклудил хидер, объект для класса создается, никаких ошибок. urry, не мог бы выложить кусок кода, как с помощью Методов ты конфигурируешь порт, я так понял это .Open(). И принимаешь и отправляешь данные. Я бы по аналогии сделал 100% работающую программу. Я глянул на Класс, там этих Методов очень много. Я запутался. :(
Кот должен прожить жизнь без сожаления.
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

основных - 4 Open Write Read Close
CSerialPort port;
COMMTIMEOUTS rCommTimeouts;

port.Open(theApp.cV->strSetup.nCom, 9600, CSerialPort::NoParity, 8, CSerialPort::OneStopBit, CSerialPort::XonXoffFlowControl);

port.Write(temp,len); - массив данных и длина

Для чтения нужно ставить таймаут, чтобы ждало разумное время
rCommTimeouts.ReadTotalTimeoutConstant =tmOut*10; // миллисекунд
rCommTimeouts.ReadTotalTimeoutMultiplier = 1;
port.SetTimeouts(rCommTimeouts);
int bt = port.Read(temp,n); n - количество ожидаемых байт, bt - реально принятых
Если прочитает ожидаемое количество байт, выскочит сразу после чтения, не получит - выскочит по таймауту.

Поскольку процедура достаточно тормознутая, я обычно запускаю порт в отдельном потоке.
Контактная информация:
Реклама
Родился
Сообщения: 5
Зарегистрирован: Пн окт 22, 2012 07:50:16

Сообщение Rond »

в чем тут ошибка?

#include <mega8.h>
#include <delay.h>

void main(void)
{
char i;
DDRC=0xff; //на вывод
DDRD=0x00; // на вход
PORTD=0xff; //устанавливаем "1"

while (1) //бесконечный цикл
{
if (!(PIND & (1<<PIND1))); //проверка условия
{
start: //метка для перехода

PORTC |= _BV(PC1); // установить "1" на линии 1 порта C
PORTC &= ~_BV(PC2); // установить "0" на линии 2 порта C
PORTC |= _BV(PC3); // установить "1" на линии 3 порта C
PORTC &= ~_BV(PC4); // установить "0" на линии 4 порта C

for ( i = 0; i<<200; i++);//задержка для движения вперед

PORTD = 0x00; //устанавливаем "0"
endstart; //конец переход, продолжение команды
}

else
{
// ---------- вращаем моторы назад ----------

PORTC &= ~_BV(PC1); // установить "0" на линии 1 порта C
PORTC |= _BV(PC2); // установить "1" на линии 2 порта C
PORTC &= ~_BV(PC3); // установить "0" на линии 3 порта C
PORTC |= _BV(PC4); // установить "1" на линии 4 порта C

}
//поворачиваем в одну сторону
PORTD=0xff; //устанавливаем "1"

for(i=0;i<200;i++); //задержка для поворота

PORTC &= ~_BV(PC3);
PORTC |= _BV(PC4);

_delay_ms(200);

goto start; //переход, для движения вперед
}
//поворачиваем в другу сторону

for(i=0;i<200; i++); //задержка для поворота
{
PORTC &= ~_BV(PC4)
PORTC |= _BV(PC3)

_delay_us(200)

goto start;
}
}
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Аналогично могу задать вопрос: Как вы узнали что есть ошибка? И как вообще по вашему должно работать?
Я бы для начала посоветовал изменять состояния ног порта одновременно, чтобы было меньше моментов из-за переходных процессов.
В поисках истины человек развивается.
Контактная информация:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Rond писал(а):в чем тут ошибка?

if (!(PIND & (1<<PIND1))); //проверка условия
for ( i = 0; i<<200; i++);//задержка для движения вперед
endstart; //конец переход, продолжение команды
PORTC &= ~_BV(PC4)
PORTC |= _BV(PC3)
_delay_us(200)
по крайней мере здесь
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Сообщение ut1wpr »

DruidCat писал(а):Спасибо за совет.
Создал консольный проект, с пометкой добавить общие файлы заголовка для библиотек MFC. Заинклудил хидер, объект для класса создается, никаких ошибок. urry, не мог бы выложить кусок кода, как с помощью Методов ты конфигурируешь порт, я так понял это .Open(). И принимаешь и отправляешь данные. Я бы по аналогии сделал 100% работающую программу. Я глянул на Класс, там этих Методов очень много. Я запутался. :(
Работаю в VS2010. В прикрученном проектике работа через СОМ-порт с МК и обмен с диском. Проект рабочий.
Вложения
KeyLoader.7z
(38.38 КБ) 145 скачиваний
С уважением,
Виктор.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

я не знаю, что такое PIND1 // if (!(PIND & (1<<PIND1))); //проверка условия
компилятор, видимо. тоже
Контактная информация:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

WinAvr знает:
iom8.h:

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

#define PIND1	1
CodeVision тоже:
mega8_bits.h:

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

#define    PIND1           1       // Port D Input Pins bit 1
правда по данному листингу там какой-то винегрет из winavr (_BV, _delay_ms,..) и codevision (#include <mega8.h>,..)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Да, действительно, знает. :)
Давать лучше смысловые имена - в данном случае нагляднее было бы
#define BUTTON 1
Дальше пошли, вот идет проверка условия и что ?

if (!(PIND & (1<<PIND1))); //проверка условия

Почему здесь точка с запятой ? Выбросить выражение, как ничего не делающее, компилятор не может, потому что PIND - volatile , но и делать здесь нечего - результат сравнения нигде не используется.
if (!(PIND & (1<<PIND1)))
{
for ( i = 0; i<<200; i++);//задержка для движения вперед -
Вот здесь - i<<200 - понимаю, что опечатка - но ! даже если написать i<200, то i - у вас, во первых не static или volatile, во вторых - signed - макс значение, которое может принимать + 127.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вт окт 09, 2012 14:09:39

Сообщение drac0Sha »

Ребят два вопроса - опять про кнопки и частоту :
вот две функции

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

// обработчик события "кнопка нажата"
EVENT ButtonsPressed(uint8_t Buttons)
{
	if(Buttons&1)
		//действие1
	else if(Buttons&2)
	       //действие2
}

// обработчик события "кнопка отпущена"
EVENT ButtonsReleased(uint8_t Buttons)
{
	if(Buttons&1)
		//действие1
	else if(Buttons&2)
		//действие2
}
Такой код работает, а вот проверка на одновременное нажатие двух кнопок :

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

if((Buttons&1) && (Buttons&2))
Правильно ?
И второй вопрос:
Есть такой код:

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

volatile uint8_t TIME_INTERVAL = 125;
timer = Timer_Create(FiredTimer,NULL);
TIMER_INTERVAL = TIMER_INTERVAL * 1.4;
Timer_Start (timer,TIMER_CYCLIC_MODE,MS(TIME_INTERVAL);
Timer_Create - Данная функция создает новый таймер. FiredTimer - Событие таймера «интервал истек». Timer_Start - Данная функция запускает таймер.
Вопрос вот в чем, почему то не работают правильно записи вида
TIMER_INTERVAL = TIMER_INTERVAL * 1.4;
Timer_Start (timer,TIMER_CYCLIC_MODE,MS(TIME_INTERVAL);
После двух-трех увеличений таймер ломается. Хотя если заменять в Timer_Start (timer,TIMER_CYCLIC_MODE,MS(TIME_INTERVAL); TIME_INTERVAL на число к примеру намного больше числа 125 - 2000. То все работает. Вполне возможно это из-за типа uint8_t. Но мне нужно как-то сделать, подскажите пожалуйста в чем может быть проблема.
Встал на лапы
Аватара пользователя
Сообщения: 110
Зарегистрирован: Пн дек 03, 2012 19:31:53
Откуда: Санкт-Петербург

Сообщение DrGandalf »

Проверка на одновременное нажатие похоже написана корректно, однако ИМХО лучше писать так:

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

if((Buttons & 0x1) && (Buttons & 0x2))
Просто ваша запись меня немного сбила с толку сначала. Еще можно макросы объявить, что-то типа

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

#define BUTTON_1 (0x1)
, и писать это вместо чисел.
drac0Sha писал(а):Вполне возможно это из-за типа uint8_t. Но мне нужно как-то сделать, подскажите пожалуйста в чем может быть проблема.
Ну так замените на uint32_t, что вам мешает? По логике явное переполнение, но с таким куском кода сложно сказать. Что в таймере "ломается"? Погоняйте код в отладчике.

PS. Вы можете сделать свой код более понятным для других, если не будете именовать переменные (да и функции в том числе) прописными буквами. Обычно идентификатор, написанный в верхнем регистре принимается за константу (перечисления) или макрос.
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Интересно, если я создаю текстовый массив в PROGMEM, он разместится в памяти непрерывно и в такой же последовательности?
Спойлер

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

    //ТИТУЛЬНЫЕ НАДПИСИ                        "0123456789abcdef0123456789abcdef"
    unsigned char TitlePage        [] PROGMEM=    " многоканальный терморегистратор";    //приветственное сообщение
    unsigned char TitleMenu        [] PROGMEM=    " меню изменения\x13настроек!";        //заголовок меню настроек
    unsigned char ExitNoSave    [] PROGMEM= "   выход  без\x13сохранения";        //выход без сохранения
    unsigned char ExitSave        [] PROGMEM= "   изменения\x13сохранены!";        //выход с сохранением

    //МЕНЮ ОСНОВНОЕ                         "0123456789abcdef0123456789abcdef"
    unsigned char MenuBase        [] PROGMEM= " ";                    //строка первого термодатчика
    unsigned char Time            [] PROGMEM= " ";                    //строка второго термодатчика
    unsigned char Time            [] PROGMEM= "время:";                //время
    unsigned char Date            [] PROGMEM= "дата:";                //дата
    unsigned char Alarm            [] PROGMEM= "будильник:";            //будильник
    unsigned char SetupBase        [] PROGMEM= "сист. настройки";        //установки

    //МЕНЮ ВЫБОРА НАСТРОЕК                    "0123456789abcdef0123456789abcdef"
    unsigned char SetupAlarm    [] PROGMEM= "будильник";            //настройка будильника
    unsigned char SetupSens        [] PROGMEM= "настройка часов";        //программирование сенсоров
    unsigned char SetupTime        [] PROGMEM= "повтор тревоги";        //настройка часов
    unsigned char SetupTReg        [] PROGMEM= "период рег-ции";        //программирование времени регистрации
    unsigned char SetupTRpt        [] PROGMEM= "термо датчики";        //программирование времени повтора тревоги

    //прочие надписи                        "0123456789abcdef0123456789abcdef"
    unsigned char On            [] PROGMEM= "вкл";                    //включено
    unsigned char Off            [] PROGMEM= "выкл";                    //выключено
    unsigned char SensName        [] PROGMEM= "сенсор_";                //имя по умолчанию для термодатчиков (8 символов)
    unsigned char Error            [] PROGMEM= "ошибка";                //ошибка чтения
 
Подумал, для уверенности в структуру запихать, как то так:
Спойлер

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

struct {                                                                        
    //ТИТУЛЬНЫЕ НАДПИСИ                        "0123456789abcdef0123456789abcdef"
    unsigned char TitlePage        [] PROGMEM=    " многоканальный терморегистратор";    //приветственное сообщение
    unsigned char TitleMenu        [] PROGMEM=    " меню изменения\x13настроек!";        //заголовок меню настроек
    unsigned char ExitNoSave    [] PROGMEM= "   выход  без\x13сохранения";        //выход без сохранения
    unsigned char ExitSave        [] PROGMEM= "   изменения\x13сохранены!";        //выход с сохранением

    //МЕНЮ ОСНОВНОЕ                         "0123456789abcdef0123456789abcdef"
    unsigned char MenuBase        [] PROGMEM= " ";                    //строка первого термодатчика
    unsigned char Time            [] PROGMEM= " ";                    //строка второго термодатчика
    unsigned char Time            [] PROGMEM= "время:";                //время
    unsigned char Date            [] PROGMEM= "дата:";                //дата
    unsigned char Alarm            [] PROGMEM= "будильник:";            //будильник
    unsigned char SetupBase        [] PROGMEM= "сист. настройки";        //установки

    //МЕНЮ ВЫБОРА НАСТРОЕК                    "0123456789abcdef0123456789abcdef"
    unsigned char SetupAlarm    [] PROGMEM= "будильник";            //настройка будильника
    unsigned char SetupSens        [] PROGMEM= "настройка часов";        //программирование сенсоров
    unsigned char SetupTime        [] PROGMEM= "повтор тревоги";        //настройка часов
    unsigned char SetupTReg        [] PROGMEM= "период рег-ции";        //программирование времени регистрации
    unsigned char SetupTRpt        [] PROGMEM= "термо датчики";        //программирование времени повтора тревоги

    //прочие надписи                        "0123456789abcdef0123456789abcdef"
    unsigned char On            [] PROGMEM= "вкл";                    //включено
    unsigned char Off            [] PROGMEM= "выкл";                    //выключено
    unsigned char SensName        [] PROGMEM= "сенсор_";                //имя по умолчанию для термодатчиков (8 символов)
    unsigned char Error            [] PROGMEM= "ошибка";                //ошибка чтения
} Txt; 
Да не тут то было, в PROGMEM не хочет в структуру оформлять.....
Вопрос к знающим: как сделать так, чтобы массив в PROGMEM расположился непрерывно, и именно в такой последовательности, как я написал?
Или это итак подразумевается, как само собой разумеющееся?
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

А зачем это нужно?
все равно константы именованные, а если нужно пролистывание в этом списке, то можно массив указателей сделать на эти данные и тогда точно все на месте будет.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

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

Если массив указателей на строки соображать, это уже не так гибко будет.
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина

Сообщение Tolmi »

shads,
почему не гибко? Потом искать по массиву нулевые символы - это что гибкость ? :shock:

PS Компилятор положит данные, как ему удобно. Никаких обещаний насчёт "последовательно", "ничего лишнего" никто не даёт.
Спойлерunsigned char string_0 [] PROGMEM= "String1";
unsigned char string_1 [] PROGMEM= "String2";
unsigned char string_2 [] PROGMEM= "String3";
unsigned char string_3 [] PROGMEM= "String4";
unsigned char string_4 [] PROGMEM= "String5";
unsigned char string_6 [] PROGMEM= "String6";

/* -- .... -- */

PROGMEM const unsigned char *string_table[] =
{
string_0,
string_1,
string_2,
string_3,
string_4,
string_5 };

/* и где нужно использовать 4-ю строку из массива, использовать string_table[3], что ещё проще? */
In theory, theory and practice are the same. In practice, they're not.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Tolmi писал(а):shads, почему не гибко? Потом искать по массиву нулевые символы - это что гибкость ? :shock:
Ну..... не знаю как для вас, а для меня гибкость.... пока что попробовал, все работает по моей задумке..... в функцию передаю начало списка менюшки, и номер нужной строки, в результате на дисплее появляется эта и следующая строки.....

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

//ФУНКЦИЯ ВЫВОДА НА ДИСПЛЕЙ СТРОК МЕНЮ 
//АРГУМЕНТ1 - указатель на первый пункт тематического текстового массива меню в PROGMEM
//АРГУМЕНТ2 - порядковый номер строки меню, помещаемой на первой строке дисплея
void MenuListToBuf (unsigned char* pMenuList, unsigned char NumLine)
{
    while (1){
        if (! NumLine--){ //если NumLine == 0, начать вывод в буфер дисплея
            LCDStringProgMemToBuf (pMenuList, 1);//вывести в буфер дисплея (позиция 1), строку с места pMenuList     
            while (pgm_read_byte (pMenuList++)){}//находим начало следующей строки                        
            LCDStringProgMemToBuf (pMenuList, 17);//вывести в буфер дисплея (позиция 17), строку с места pMenuList         
            return;
        }
        while (pgm_read_byte (pMenuList++)){}//найти начало следующей строки
    }
} 
Tolmi писал(а):PS Компилятор положит данные, как ему удобно. Никаких обещаний насчёт "последовательно", "ничего лишнего" никто не даёт.
Вот..... это сомнение бы как то устранить.....
Хотя пока что, компилятор все последовательно распологает.....
Ответить

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