a_sergeevich

Язык Си Для Микроконтроллеров

1 501 сообщение в этой теме

my504    155

Разделите задачу ПОПЕРЕК. Сначала заставьте обычный пин контроллера переключаться в противоположное состояние при нажатию на кнопку.

Учтите, что реальная кнопка дребезжит, т.е. в момент нажатия МНОГОКРАТНО переходит в противоположное состояние в течении ВРЕМЕНИ ДРЕБЕЗГА. Если опрашивать кнопку с периодом более, чем время дребезга и фиксировать два одинаковых подряд состояния входа с кнопки, то можно создать искомое Вами.

Работайте...

Поделиться сообщением


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

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
sibiryak    0

Интересный и главное, вроде бы, простой вариант и никакой переменной объявлять ненадо. Попробую. Спасибо. Если будут у кого еще предложения, буду рад прочитать и другие варианты. Новичкам вроде меня всякое может пригодится. :)

у меня еще вопрос. В микроСи есть функция button, в которой имеется время дребезга, а размерности этого временеи не описано. Какая размерность этого времени: сек, мс или мкс?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    155

Не знаю, но логично предположить миллисекунды. А вообще, рекомендую написать антидребезг САМОМУ, без библиотеки.

Насчет не нужно переменной - это вряд ли. По сути нужна память состояния до следующего опроса.

Изменено пользователем my504

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
sibiryak    0

Все, нашел. В мс. И насчет переменной Вы правы, там не обойтись, если я правильно понимаю.

Вот что у меня получилось из того, что я хотел (я понимаю, что это черновой вариант). Может кто проверит и поправит. Антидребезг я использовал библиотечный, т.к. я тока начинаю разбираться в Си. Я пробую компилировать, но он у меня начинает ругаться с самого начала. Скорей всего это из-зи того, что я неправильно обращаюсь к определенному биту порта. Не скажете как правильно в микроСи 8 обратиться к биту? Или что здесь неправильно?

char oldstate;

void signalon () {

if (PORTB.F6 == 1) {

PORTB.F3 = 1;

switch (PORTA) {

case PORTA.F0 == 0: PORTB.F0 = 1;

delay_ms (200);

PORTB.F0 = 0;

case PORTA.F0 == 0: PORTB.F1 = 1;

break;

default: PORTB.F3 = 1; }

}

}

void signoff () {

if (PORTB.F6 == 0)

PORTB.F4 = 1;

}

main () {

STATUS = 0B00100000;

OPTION_REG = 0b10000111;

TRISA = 0b00011111;

TRISB = 0;

PORTB = 0;

STATUS = 0;

while (1) {

if (Button(&PORTA, 0, 1, 1)) oldstate = 1;

if (oldstate && Button(&PORTB, 0, 1, 0)) {

PORTB.F6 = ~PORTB.F6;

oldstate = 0;

}

signalon ();

signoff ();

}

}

Изменено пользователем sibiryak

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    484

Из Мануала на MicroC :

Доступ к отдельным битам

mikroC позволяет получить доступ к отдельным битам 8-битовых переменных, типа char и unsigned short. Просто используйте операцию доступа к элементу структуры (.) с этой переменной, за которой должен следовать один из идентификаторов F0, F1, … , F7, где F7 означает самый старший бит.

Пример:

// Если RB0 установлен, установить RC0:
if (PORTB.F0) PORTC.F0 = 1

;

При этом не требуется никаких дополнительных описаний: данный тип выборочного доступа является внутренней особенностью mikroC и может использоваться в любом месте программы. Идентификаторы F0–F7 указываются большими или маленькими буквами и только в специально отведенном для них месте. Вы можете использовать свои собственные элементы структуры вместо F0–F7.

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

// Очистка бита TMR0F:
INTCON.TMR0F = 0;

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

Я пробую компилировать, но он у меня начинает ругаться с самого начала.
Не плохо бы увидеть ошибки, выдаваемые компилятором. Экстрасенсов на форуме нет !

Поделиться сообщением


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

Ошибка твоя вот в чём.

Ты не правильно применяешь оператор switch case. Ты пишешь case PORTA.F0 == 0.... , а в мануале по Си указан следующий синтаксис case value1: операторы. Значение value1 должно быть простой константой либо константным выражением. Твоё условие PORTA.F0 == 0 не отвечает ни первому ни второму.

Поэтому просто замени switch case на обычные условия if...else.

Примерно так:

char oldstate;

void signalon () {
if (PORTB.F6 == 1) {
PORTB.F3 = 1; }

if( PORTA.F0 == 0 ) {PORTB.F0 = 1;
Delay_ms (200);
PORTB.F0 = 0; }
if(PORTA.F0 == 0) PORTB.F1 = 1;

else
   PORTB.F3 = 1;
}


void signoff () {
if (PORTB.F6 == 0)
PORTB.F4 = 1;
}
main () {
STATUS = 0B00100000;
OPTION_REG = 0b10000111;
TRISA = 0b00011111;
TRISB = 0;
PORTB = 0;
STATUS = 0;
while (1) {
if (Button(&PORTA, 0, 1, 1)) oldstate = 1;
if (oldstate && Button(&PORTB, 0, 1, 0)) {
PORTB.F6 = ~PORTB.F6;
oldstate = 0;
}
signalon ();
signoff ();
}
}

И ещё функции delay_ms в микроСи нету есть Delay_ms, регистр имеет значение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
sibiryak    0

Спасибо большое! :) Буду дальше изучать. Спасибо за цитату из мануалки. Я думал, что всю ее перечитал и не раз. Видимо пропустил. :unsure:

Изменено пользователем sibiryak

Поделиться сообщением


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

Под мануалом я имел ввиду не русский хелп для микроСи, а книгу по языку, которая у меня всегда под рукой. Называется "Программирование на языке Си" автор Стефан Кочан, очень рекомендую.

Извиняюсь если ввёл в заблуждение :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
sibiryak    0

Под мануалом я имел ввиду не русский хелп для микроСи, а книгу по языку, которая у меня всегда под рукой. Называется "Программирование на языке Си" автор Стефан Кочан, очень рекомендую.

Извиняюсь если ввёл в заблуждение :)

А у тебя нет ссылки на эту книгу, где ее можно спокойно качнуть?

Поделиться сообщением


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

Ты уже не первый кто спрашивает у меня ссылку на эту книгу. К сожалению у меня ссылки такой нет т.к книга у меня в бумажном виде и сколько я ни пытался найти её в электронном виде, не нашёл. Кстати такую книгу лучше иметь именно в бумажном виде, да и стоит она не так уж дорого, в интернет магазинах от 200 до 250 рублей.

Ну как у тебя дела с твоей программой, получается что нибудь ?

Да, вот ссылка http://zalil.ru/29894591 тоже отличная книга по языку Си, учись на здоровье :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
sibiryak    0

Ты уже не первый кто спрашивает у меня ссылку на эту книгу. К сожалению у меня ссылки такой нет т.к книга у меня в бумажном виде и сколько я ни пытался найти её в электронном виде, не нашёл. Кстати такую книгу лучше иметь именно в бумажном виде, да и стоит она не так уж дорого, в интернет магазинах от 200 до 250 рублей.

Ну как у тебя дела с твоей программой, получается что нибудь ?

Да, вот ссылка http://zalil.ru/29894591 тоже отличная книга по языку Си, учись на здоровье :)

Спасибо. Продолжаю дальнейшую разработку своей проги, пока все ок. Спасибо за помощь! :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
sibiryak    0

я тут проверил в протеусе прогу и увидел, что не то, что я хотел получается. А получается вот что: при включении у меня сразу горят два диода RB3 и RB4 и после нажатия кнопки RA1 (здесь уже точно должен гореть один из светодиодов) переключения между ними нет. Не можншь подсказать в чем дело?

char oldstate;

void signalon () {

if (PORTB.F6 == 1) PORTB.F3 = 1;

if( PORTA.F0 == 0 ) {PORTB.F0 = 1;

Delay_ms (200);

PORTB.F0 = 0; }

if(PORTA.F0 == 0) PORTB.F1 = 1;

else

PORTB.F3 = 1;

}

void signoff () {

if (PORTB.F6 == 0)

PORTB.F4 = 1;

}

main () {

STATUS = 0B00100000;

OPTION_REG = 0b10000111;

TRISA = 0b00011111;

TRISB = 0;

PORTB = 0;

STATUS = 0;

while (1) {

if (Button(&PORTA, 1, 10, 1)) oldstate = 1;

if (oldstate && Button(&PORTB, 1, 10, 0)) {

PORTB.F6 = ~PORTB.F6;

oldstate = 0;

}

signalon ();

signoff ();

}

}

и еще вопросик. Когда у меня RA=1 светодиод RB6 моргает, т.е. инверсия происходит постоянно. Разве он не должен изменять свое состояние только после того как RA1=0? Кнопка с NC контактами

Изменено пользователем sibiryak

Поделиться сообщением


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

Прокомментируй код, где, что ты делаешь.

Ну а на вскидку первая ошибка тут

if (Button(&PORTA, 1, 10, 1)) oldstate = 1;

if (oldstate && Button(&PORTB, 1, 10, 0))

видишь, ты кнопку пасёшь на PORTA, а во втором условии пишешь PORTB.

И ещё дам один хороший совет по отладке программ.

Отладчики, протеус - это всё хорошо, но не поленись составь на бумаге трассировочную таблицу в которую занеси все переменные и прям по строкам программы идёшь и в табличке эти переменные изменяешь. Очень хорошо помогает отлавливать ошибки. Так же твою прогу можно прогнать в микроСи-шном отладчике, там сразу будет видно состояние портов, что в них и как.

Ну, а пока от комментируй код :) и делай так всегда, когда хочешь получить помощь.

Удачи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
sibiryak    0

Спасибо! Я и остальные свои ошибки нашел. А не подскажете, можно ли использовать while в подпрограммах или он используется тока в основной программе?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    484

А почему бы нет ? Конечно можно. Только используйте аккуратно, дабы не зацыклить программу на вечно :wacko:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Noglamour    0

Привет всем.

У меня возник такой вопрос. Пользуюсь MPLab, компилятор MCC18. Контроллер PIC18F2550

Выполняю задержку таким образом в файле user.c.

                       INTCON = 0x20;                //disable global and enable TMR0 interrupt
		INTCON2 = 0x84;               //TMR0 high priority
		RCONbits.IPEN = 1;
		INTCONbits.GIE = 1;
		T0CON = 0x61;
		TMR0L = 0;
		INTCONbits.TMR0IF = 0;
	        T0CONbits.TMR0ON = 1;
		x=0;	
                while(x<12)
		{

		}

обрабатываю прерывание в файле interrupt.c

#pragma interrupt high_isr
void high_isr(void)
{
if(INTCONbits.TMR0IF == 1);
{

INTCONbits.TMR0IF = 0;
x++;
} 
}

Как сделать, чтобы переменная x объявленная в user.c была видна и её можно было изменять в interrupt.c

Изменено пользователем Noglamour

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
rtfcnf    1

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

1. в файле "interrupt.c" напишите extern int x;

если не прокатит:

2. вынесите объявления переменной из user.c в файл user.h, если нет у Вас user.h, то создайте его

в user.c напишите #include "user.h"

в interrupt.c напишите #include "user.h"

extern int x;

если опять не прокатит пишите какие ошибки выдает компилятор, будем думать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Noglamour    0

Первый способ я сделал, но программа не выходит из цикла, х почему-то всё равно равно 0. Может я напутал что-то с прерываниями?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mil_alex    17

переставьте x++ выше по тексту, вне блока if - чтобы убедиться, что прерывание обрабатывалось.

кстати, после 32 тысяч повторов x будет отрицательным B)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Noglamour    0

переставьте x++ выше по тексту, вне блока if - чтобы убедиться, что прерывание обрабатывалось.

кстати, после 32 тысяч повторов x будет отрицательным B)

x обнулятся перед while

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Noglamour    0

в общем, проблема решена. Я выставил бит в регистре T0CON для тактирования от внешнего источника.От внутреннего источника всё работает.

Как настроить работу от внешнего кварца?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
rtfcnf    1

x обнулятся перед while

Ваш код:

x=0; 
while(x<12)

а я то думал что не так посоветовал :D

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mil_alex    17

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    155

Как настроить работу от внешнего кварца?

Работу чего? Контроллера или первого таймера?

Если контроллера - это в конфиге (заголовок листинга). Там же указывается включение PLL (учетверение частоты кварца).

Если речь о первом таймере, то там LP генератор конфигурируется в T1CON, но при этом уже использовать LP в качестве системного нельзя.

Обращаю Ваше внимание на правильный выбор конфигурации кварцевого генератора. При частоте от 4 МГц и выше нужно выбирать HS, а ниже 4 МГц - XT. Район 1...4 МГц допускает оба типа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Andrey_Ch8    1

Не могу найти толковои литературы по пикам и си, то что а_сергеевич выкладывал уже не работает , перезалеите пожалуиста или поделитесь хорошей книгои.

Поделиться сообщением


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

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

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

  Разрешено не более 75 смайлов.

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

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

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

Загрузка...

  • Похожие публикации

    • Автор: Артемон
      Всем привет. Просьба посодействовать в исправлении кода для термометра. Так как сам я в этом новичек, то код собирал из трех чужих проектов. Реализация такова, подключение термопары через микруху Max6675 к Atmega и вывод данных на LCD экран. В архиве прилагаю проект Atme Studio 7 и принт скрин из Протеуса. Ошибка заключается в неправильных показаниях температуры

      Test1.rar
      Вот код, чтоб не скачивать проект.

      #define F_CPU 1000000UL #include <util/delay.h> #include <avr/io.h> #include "max6675.h" #include "LCD.h" uint16_t gettemp(void); //Funktionsdeklarationen void initavr(void); //gettemp () returns absolute Temperature in Temp * 4 °C - in 1/4°-steps // uint16_t gettemp(void){ //Temperatur holen. uint8_t bit = 0, bitnr = 12; //Variablen uint8_t foo1 = 0; uint16_t Rohdata = 0; CS_Port &= ~(1 << CS); //Chip select anlegen for(foo1 = 0 ; foo1 < 16 ; foo1++){ //16 Bits einlesen bit = 15 - foo1; //Die Aktuelle Bitnr berechnen. SCK_Port |= (1 << SCK); //SCK hi if((bit <= 14) && (bit >= 3)){ //Einfach mal die 12 relevanten von den 16 Bits ausfiltern if((SO_Pin & (1 << SO))){ //WENN SO 1 ist, dann... bitnr--; //zдhlen wir runter... Rohdata |= (1 << bitnr); // und schieben eine 1 an bit x }else{ //WENN dem NICHT so ist, dann... bitnr--; //zдhlen wir runter... Rohdata &= ~(1 << bitnr); //und schieben eine 0 an bit x } }else{ //weis au nimmer, was das soll. bitnr = 12; } SCK_Port &= ~(1 << SCK); //SCK LO } CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. return Rohdata; //Das ist doch mal was ;D } // getTC() returns 0 if Thermocouple is not connected, 255 if thermocuple is connected // (to enable this feature T- must be connected to GND) uint8_t getTC(void){ //Temperatur holen. //Variablen uint8_t TC = 0; uint8_t foo1 = 0; CS_Port &= ~(1 << CS); //Chip select anlegen for(foo1 = 0 ; foo1 < 16 ; foo1++){ //16 Bits einlesen //Die Aktuelle Bitnr berechnen. SCK_Port |= (1 << SCK); //SCK hi if(foo1 == 2){ //das 3. bit ist fьr uns relevant. if((SO_Pin & (1 << SO))){ //WENN SO 1 ist, dann... TC = 0; }else{ //WENN dem NICHT so ist, dann... TC = 255; } } SCK_Port &= ~(1 << SCK); //SCK LO } CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. return TC; //Das ist doch mal was ;D } //Initiates the MAX6675 and IO-pins void init_6675(void){ //AVR initialisieren SO_DDR &= ~(1 << SO); CS_DDR |= (1 << CS); SCK_DDR |= (1 << SCK); //IOs setzen SO_Port |= (1<<SO); //Pullups an. (Wichtig fьr MAX6675, der kann nicht anders, hab ich festgestellt... CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. SCK_Port &= ~(1 << SCK); //SCK LO } int main(void) { init_port();// инициализируем порт ЖКИ lcd_init();// инициализируем ЖКИ init_6675(); while (1) { char buffer[8]; int temp; temp = gettemp(); temp /=4; lcd_gotoxy(0,0);//перемещаем курсор в верхний левый угол sprintf(buffer, "t=%i\xdf\C ", temp); // так как тут не плавающая запятая то числа с запятой записываются так %i.%i, код градуса записывается так \xdf lcd_putstring(buffer); } }
      вставляете код пользуйтесь тегами [CОDE][/CОDE] редактора сообщений, кнопка <>
    • Автор: igoryan
      нужно ли обрабатывать RESET просто компилятор не видит RESET_vect?
    • Автор: P32L
      Натолкните на мысль пожалуйста.Смысл в следующем.Нужно изменять задержку(Delay) из EEPROM. Контроллер PIC , язык СИ.
      Как реализовать чтение числа из ипрома ? Если не затруднит, то кусочек кода был бы очень кстати.
    • Автор: Zver2011
      Здравствуйте! Недавно начал изучать МК AVR. Читаю книги Белова. Пользуюсь программами CVAVR и Proteus. По урокам, собирал все в железе. По готовым примерам кода конечно же мне легко учиться и все в принципе понятно из описания, хоть и в программировании не силен, но как только начинаешь создавать что то свое - начинаются проблемки.
      В общем я создаю что то вроде музыкального светильника, который должен включаться от звука (голоса). Датчик звука пытаюсь реализовать на компараторе, плавное включение света - ШИМ, а генерация мелодии (пищалки) благодаря таймеру Т1 и его прерыванию. Куски кода брал из разных чужих самоделок, вот только объединить не удается.
      В железе работает как будто цветомузыка какая-то. Мелодия не играет, Я думаю это из-за неправильной конфигурации компаратора, а также схемы. Вот это основной вопрос у меня. Ну и собственно основной цикл программы, там я думаю тоже накосячил.
      Помогите мне разобраться до конца, понять ошибки в коде, мне самому интересно вот только С - язык тяжеловатый на мой взгляд и без помощи знающих не обойтись))

      КОД.txt
    • Автор: sensey88
      Продам счетчики бета-гамма излучения новые заводская упаковка
      Си1Г (79г) 62 шт. 5000р
      Си21БГ (79г) 49 шт. 350р
      Си22БГ (79г) 70 шт. 700р
      Си3БГ (84г) 20 шт. 300р
      Си3БГ (78г) 46 шт. 250р
      Си3БГ (77г) 10 шт. 250р
      Си3БГ (79г) 18 шт. 250р
      Си3БГ (75г) 10 шт. 200р
      Си37Г (80г) 40 шт. 400р
      Си37Г (76г) 24 шт. 350р
      Си37Г (79г) 16 шт. 350р
      Си33Г (78г) 28 шт. 450р
      Си33Г (77г) 15 шт. 450р
      СБТ13 (78г) 2 шт. 3000р
      СБТ13 (76г) 3 шт. 2700р
      СБТ13 (69г) 3 шт 2500р.
      Си8Б (79г) 1 шт. 2500р
      Си8Б (78г) 1 шт. 2500р
      СБТ10 (79г) 3 шт. 4500р
      8 (910) 7051241 Евгений
      bishop-x@yandex.ru