Снова про шаблоны c++ в микроконтроллерах

Типы данных в Си

-Базовые типы данных: char, int, float, double.

-Модификаторы знака: signed, unsigned.

-Модификаторы знака: long, short.

void — тип без значения

При этом следущие типы равны:

В Си логический тип реализован неявно (с помощью int): false = нуль, true = не нуль.

Введение псевдонимов для ранее описанных типов данных:

typedef тип имя

где тип — любой существующий тип данных, имя — новое имя для этого типа.

Пример: typedef unsigned char byte;

Преобразование типов:

Если операнды операции имеют разные типы, то происходит неявное приведение типов:

(чтобы здесь получить 0.4 нужно было бы написать x=2.0/5 или 2/5.0)

Явное приведение типов:

Принудительное преобразование типов:

(тип) выражение;

(желательно вообще избегать преобразования типов)

Переменные и константы

Переменная представляет собой блок памяти, на который мы ссылаемся по её имени (идентификатору).

Декларация переменных (вместе с инициализацией):

тип идентификатор = инициатор;

Например,

Здесь «;» — составляющая часть конструкции, завершающая часть.

Допустима (хотя и редко используется) запись: const x = 100; (по умолчанию int).

Квалификаторы (или «модификаторы доступа»): const, volatile.

const — означает, что переменные не могут изменяться во время выполнения программы; инициалиировать можно только при декларации;

volatile — содержимое переменной может измениться само собой (используется в многопоточных программах при взаимодействии процессов)

Возможен вариант const volatile, когда писать могут только снаружи.

Спецификторы хранения (описатель класса памяти): auto, register, extern, static.

auto — локальные переменных (по умолчанию) — программный стек.

register — просьба компилятору положить переменную в регистр ЦПУ (но он эту просьбу редко выполняет);

extern — объявление (declaration) переменных, но не определение (definition) (определение где-то в другом месте); определение может идти ниже по файлу (но как глобальная) или в другом файле.

static — статические локальные переменные, которые хранят своё значение между вызовами функций (они предпочтильнее, чем глобальные переменные). Статические глобальные переменные видны только в пределах данного файла.

Внешние и статические объекты существуют и сохраняют свои значения на протяжении всего времени выполнения программы.

Автоматические и регистровые объекты создаются и существуют только внутри блока, в котором они описаны, и уничтожаются при выходе из этого блока.

Описание области действия идентификаторов (имен):

— внутреннее (локальное) — внутри блока {…}

— внешнее (глобальное) — вне всех блоков

Идентификатор, описанный внутри блока, известен только в этом блоке (локальный идентификатор).

Идентификатор, описанный на самом внешнем уровне, известен от места появления этого описания до конца входного файла, в котором он описан (глобальный идентификатор).

Стоит избегать использования глобальных имен.

Переменные с классом памяти static видны только в пределах текущего блока (для локальных) или в пределах файла (для объявленных глобально).

Статические переменные хранятся в сегменте данных (data) и по умолчанию инициализируются нулем. Т.е. память под static-переменные выделяется при старте программы и существует до конца программы.

Замечание: Инициализация выполняется одни раз при выделении памяти!

Статическими могут быть также функции. Такая ф-ция может исп-ся только внутри данного файла.

Следует различать присваивание и инициализацию:

— Присваивание: имя_переменной = выражение;

— Многочисленное присваивание: x = y = z = 0;

— Инициализация переменных: тип имя_переменной = константа;

Константы

Константы являются частью машинных команд и под них память не выделяется.

Константы бывают:

— целые:

10-я система: 127; -127; +127;

8-я система: 0127; (начинается с нуля — значит 8-ричная!)

16-я система: 0x7F; (x или X, f или F — регистр не влияет)

— вещественные: 3.14; 2. ; .25 (0 можно опускать); 2E3; 2e3; 2E-3; 2.0E+3;

— символьные: 8-битные ASCII: ‘A’, ‘=’, ‘\n’, ‘\t’, ‘\370’, ‘\xF8’ (символ градуса);

— строковые литералы (в двойных кавычках): «Hello, world!\n». Строки заканчиваются нулевым байтом — ‘\0’.

Макроопределения:

Первый год

  1. код продолжал оставаться кодом на C. Отсюда вытекают следующие достоинства:
    • проще контролировать «объекты», поскольку несложно проследить кто и где что вызывает и в какой последовательности (за исключением прерываний, но о них не в этой статье);
    • для хранения «указателя на объект» достаточно запомнить возвращенный fd;
    • если «объект» был удален, то при попытке его использовать вы получите соответствующую ошибку в возвращаемом значении функции;
  2. абстракция таких объектов над использовавшимся там HAL-ом позволяла писать настраиваемые под задачу из собственной структуры инициализации объекты (а в случае недостачи функционала HAL-а можно было прятать обращение к регистрам внутри «объектов»).
  1. если кто-то удалил «объект», а потом создал новый другого типа, то может случиться так, что новый получит fd старого и дальнейшее поведение будет не определено. Данное поведение можно было бы легко изменить ценой небольшого расхода памяти под связанный список вместо использования массива имеющего «ключ-значение» (массив по каждому индексу fd хранил указатель на структуру объекта).
  2. невозможно было статически разметить память под «глобальные объекты». Так как в большинстве приложений «объекты» создавались единожды и далее не удалялись, то это выглядело как «костыль». Тут можно было бы при создании объекта передавать указатель на его внутреннюю структуру, выделенную статически при компоновке, но это бы еще больше запутало код инициализации и нарушало бы инкапсуляцию.

Общая структура программы на Си и функция main()

Структура программы:

1. Директивы (#include)

2. Функция main();

3. Описание локальных переменных (в языке «С» лок. переменные должны идти перед инструкциями, но в С++ рекомендуется объявлять переменные в месте их использования).

4. Исполняемые инструкции.

5. Оператор завершения: return 0; (хотя компилятор Си сам добавляет return 0; автоматически) — под ОС.

Функция main()

В программе должна быть ровно одна функция main().

-1) программа под управлением ОС.

В стандарте описано всего две перегруженных функции main:

Не правильно писать main(void), т. к. ОС передает некоторые параметры.

При этом ф-ция main() должна возвращать некоторые значение — код возврата, передаваемый операционной системе, с помощью оператора return.

-2) программа для микроконтроллера:

Здесь пишется main(void), т.к. ОС там нет.

ADC_StartConversion()

  • Description  :This function does the ADC conversioin for the Selected Channel and returns the converted 10bit result
  • I/P Arguments: char(channel number)
  • Return value : int(10 bit ADC result)
 
unsigned int ADC_StartConversion(unsigned char channel)
 {
   ADMUX=channel;         
   _delay_ms(5);           
   ADCSRA=0xc1;           
   while((ADCSRA & (1<<ADIF)==); 
    return(ADCW);
 }

LCD_8_bit Mode

                       AVR LCD library for 8-bit mode
  • Filename: lcd_8_bit.c
  • Controller: Atmega Family(8,16,32,64,128)
  • Oscillator: 11.0592 MHz
  • Author: XploreLabz
  • website: www.xplorelabz.com

Note:

  • Pin connection for LCD display in 8-bit mode is as shown below.By default the LCD is connected to PORTB(databus) and PORTD(controlbus).
  • The code can be modified to connect the LCD to any of the PORTs by changing the «#define».
  • io.h contains the defnition of all ports and SFRs delay.h contains the in built delay routines(us and ms routines).
#include <avr\io.h>
#include <util\delay.h>
 
#include "lcd.h"
 
#define databus_direction DDRC      //  LCD databus Direction Configuration
#define controlbus_direction DDRD  //  LCD Control bus Direction Configuration
 
#define databus	PORTC             //	LCD databus connected to PORTB
#define control_bus PORTD        //	LCD Control bus connected to PORTD
 
#define rs 5                    // Register select pin connected 6th bit(D5) Control bus
#define rw 6                   // Read Write pin connected to 7th bit(D6) Control bus
#define en 7                  // Enable pin connected to 8th bit(D7) Control bus
 
 
/* 16x2 LCD Specification */
#define LCDMaxLines 2
#define LCDMaxChars 16
#define LineOne 0x80
#define LineTwo 0xc0
 
#define BlankSpace ' '

Общие сведения о портах микроконтроллеров AVR

Порты микроконтроллеров AVR — это устройства ввода/вывода, позволяющие микроконтроллеру передавать или принимать данные. Стандартный порт микроконтроллера AVR содержит восемь разрядов данных, которые могут передаваться или приниматься параллельно. Ножки микроконтроллера также называют пинами, контактами или выводами. Порты обозначаются латинскими буквами А, В, С и т.д. Количество портов зависит от конкретной модели микроконтроллера.

Kонфигурирование каждой линии порта (задание направления передачи данных) может быть произведено программно в любой момент времени. Входные буферы портов построены по схеме триггера Шмитта. Для линий, сконфигурированных как входные, также имеется возможность подключения внутреннего подтягивающего резистора сопротивлением 35…120 кОм между входом и проводом питания. Kроме того, если вывод (вход) с подключенным внутренним подтягивающим резистором подключить к общему проводу, он может служить источником тока.

Обращение к портам производится через регистры ввода/вывода, причем под каждый порт в адресном пространстве ввода/вывода за-резервировано по 3 адреса. По этим адресам размещаются три регистра: регистр данных порта PORTx, регистр направления данных DDRx и регистр выводов порта PINx. Разряды этих регистров имеют названия: Px7…Px0 — для регистров PORTx, DDx7…DDx0 — для регистров DDRx и PINx7…PINx0 — для регистров PINx.

Действительные названия регистров (и их разрядов) получаются подстановкой названия порта вместо символа «x», соответственно для порта A ре¬гистры называются PORTA, DDRA, PINA, для порта B — PORTB, DDRB, PINB и т.д.

Следует заметить, что «регистры» PINx на самом деле регистрами не являются, по этим адресам осуществляется доступ к физическим значениям сигналов на выводах порта. Поэтому они доступны только для чтения, тогда как регистры PORTx и DDRx доступны и для чтения, и для записи.

Таким образом, запись в порт означает запись требуемого состояния для каждого вывода порта в соответствующий регистр данных порта PORTx. А чтение состояния порта выполняется чтением либо регистра данных порта PORTx, либо регистра выводов порта PINx. При чтении регистра выводов порта PINx происходит считывание логических уровней сигналов, присутствующих на выводах порта. А при чтении регистра данных порта PORTx происходит считывание данных, находящихся в регистре-защелке порта – это справедливо как для входных, так и для выходных контактов.

Любой порт микроконтроллера AVR можно сконфигурировать как вход или как выход. Для этой цели используется регистр DDRx. На вход или выход можно сконфигурировать сразу весь порт или только отдельный его вывод (контакт, пин).

Регистр DDRx определяет, является тот или иной вывод порта входом или выходом. Если некоторый разряд регистра DDRx содержит логическую единицу, то соответствующий вывод порта сконфигурирован как выход, в противном случае — как вход. Буква x в данном случае должна обозначать имя порта, с которым вы работаете. Таким образом, для порта A это будет регистр DDRA, для порта B — регистр DDRB и т. д.

Установка драйвера для USBASP в Windows 10

Если вы используете интерфейс JTAG, вам может потребоваться установка драйвера для USBASP если он не установился автоматически. Если вы не установите этот драйвер, то вы не сможете найти порт USBASP в программе Atmel Studio. Скачать драйвер USBASP можно по этой ссылке — http://www.mediafire.com/file/z576zrku371qyjs/windows-8-and-windows-10-usbasp-drivers-libusb_1.2.4.0-x86-and-x64-bit.zip/file.

После скачивания драйвера выполните следующую последовательность действий:

1. Распакуйте из архива скачанные файлы и поместите их на рабочий стол.

2. Подсоедините модуль USBASP v2.0 к своему компьютеру.

3. Откройте в Windows диспетчер устройств (Device Manager).

4. Теперь вы можете увидеть подсоединенный USBASP в списке устройств.

5. Кликните правой кнопкой мыши по “USBasp” и выберите “Обновить драйвер (Update Driver)”.

6. Select “Произвести поиск драйвера на своем компьютере (Browse my computer for driver software)”.

7. Найдите в открывшемся окне распакованную папку с драйвером для USBASP и щелкните «Открыть».

8. Если установка драйвера прошла успешно, то вы увидите сообщение примерно такое же как на нижеприведенном рисунке – в этом случае вам уже не нужно выполнять дальнейшие инструкции в этом разделе статьи.

9. Если вы увидите сообщение об ошибке как на приведенном рисунке, то вы в этом случае должны отключить цифровую подпись драйвера.

Чтобы сделать выполните следующие шаги:

— нажмите кнопку Shift и удерживая ее нажатой перезагрузите свой компьютер (кликните Restart в меню Windows пока держите ее нажатой);

— когда ваш компьютер перезагрузится не отпускайте кнопку Shift до тех пор пока не увидите “Advanced Options (Расширенные настройки)” на синем экране;

— отпустите кнопку Shift и кликните на “Startup Settings”;

— кликните на “Troubleshoot (Устранение проблем)”;

— выберите “Advanced Options (Расширенные настройки)”;

— после этого вы увидите на экране список расширенных опций и кнопку “Restart” в правом нижнем углу – кликните на ней;

— подождите пока компьютер снова перезагрузится. После этого вы увидите на экране ряд настроек;

— в открывшемся списке настроек выберите пункт “Disable Driver Signature Enforcement (Отключить цифровую подпись драйвера)”. Чтобы ее выбрать просто нажмите кнопку «7» на вашей клавиатуре (не путать с кнопкой «F7»);

— после нажатия этой кнопки компьютер перезагрузится и цифровая подпись драйвера будет отключена;

— после этого снова выполните шаги 1-8 из данного раздела статьи и драйвер для программатора USBASP будет успешно установлен.

LCD_DisplayRtcDate()

  • Description  :This function display day,month,year read from DS1307.
  • I/P Arguments: char day,char month,char year(day,month,year should be packed BCD format,as read from DS1307)
  • Return value : none

void LCD_DisplayRtcDate(char day,char month,char year)
 {
     LCD_DataWrite(((day>>4) & 0x0f) + 0x30);
     LCD_DataWrite((day & 0x0f) + 0x30);
     LCD_DataWrite('/');
 
     LCD_DataWrite(((month>>4) & 0x0f) + 0x30);
 	 LCD_DataWrite((month & 0x0f) + 0x30);
     LCD_DataWrite('/');
 
     LCD_DataWrite(((year>>4) & 0x0f) + 0x30);
 	LCD_DataWrite((year & 0x0f) + 0x30);
 
 }

LCD_4_bit Mode

                       AVR LCD library for 4-bit mode
  • Filename: lcd_4_bit.c
  • Controller: Atmega Family(8,16,32,64,128)
  • Oscillator: 11.0592 MHz
  • Author: XploreLabz
  • website: www.xplorelabz.com

Note:

  1. Pin connection for LCD display in 4-bit mode.
  2. By default the LCD is connected to PORTB.
  3. The code can be modified to connect the LCD to any of the PORTs by changing the «#define databus PORTB».

io.h contains the defnition of all ports and SFRs delay.h contains the in built delay routines(us and ms routines)

#include <avr\io.h>
#include <util\delay.h>
 
#include "lcd.h"
 
#define databus_direction DDRB //  LCD data and Control bus Direction Configuration
 
#define databus	PORTB      //	LCD databus connected to PORTB
#define control_bus PORTB      //	LCD Control bus connected to PORTB
 
#define rs 0                // Register select pin connected 1st bit(D0) Control bus
#define rw 1                // Read Write pin connected to 2nd bit(D1) Control bus
#define en 2                // Enable pin connected to 3rd bit(D2) Control bus
 
 
/* 16x2 LCD Specification */
#define LCDMaxLines 2
#define LCDMaxChars 16
#define LineOne 0x80
#define LineTwo 0xc0
 
#define BlankSpace ' '

Кодировка инструкций

Назначения битов:

  • rrrrr = Исходный регистр
  • rrrr = Исходный регистр (R16 – R31)
  • rrr = регистр источника (R16 – R23)
  • RRRR = пара регистров источника (R1: R0 – R31: R30)
  • ddddd = Регистр назначения
  • dddd = Регистр назначения (R16 – R31)
  • ddd = Регистр назначения (R16 – R23)
  • DDDD = Пара регистров назначения (R1: R0 – R31: R30)
  • pp = пара регистров, W, X, Y или Z
  • y = бит пары регистров Y / Z (0 = Z, 1 = Y)
  • u = FMUL (S (U)) со знаком 0 = со знаком или 1 = без знака
  • s = бит сохранения / загрузки (0 = загрузка, 1 = сохранение)
  • c = вызов / прыжок (0 = прыжок, 1 = вызов)
  • cy = с переносом (0 = без переноса, 1 = с переносом)
  • e = Расширить адрес косвенного перехода / вызова с помощью EIND (0 = 0: Z, 1 = EIND: Z)
  • q = Расширить адрес программной памяти с помощью RAMPZ (0 = 0: Z, 1 = RAMPZ: Z)
  • aaaaaa = адрес пространства ввода / вывода
  • aaaaa = адрес пространства ввода / вывода (только первые 32)
  • bbb = номер бита (0–7)
  • B = битовое значение (0 или 1)
  • kkkk = 4-битная беззнаковая константа (код операции DES)
  • kkkkkk = 6-битная беззнаковая константа
  • KKKKKKKK = 8-битная константа

Atmel AVR использует много разделенных полей, где биты не являются смежными в командном слове. Инструкции загрузки / сохранения со смещением являются наиболее ярким примером, когда 6-битное смещение разбивается на три части.

Обзор набора команд Atmel AVR
1 5 1 4 1 3 1 2 1 1 1 0 9 8 7 6 5 4 3 2 1 Инструкция
NOP
1 DDDD RRRR MOVW Rd, Rr Перемещение пары регистров
1 дддд рррр MULS Rd, Rr
1 1 ддд ррр MULSU Rd, Rr
1 1 ддд 1 ррр FMUL Rd, Rr
1 1 1 ддд ты ррр FMULS (U) Rd, Rr
код операции р ддддд рррр 2-операндные инструкции
c̅y̅ 1 р ддддд рррр CPC / CP Rd, Rr
c̅y̅ 1 р ддддд рррр SBC / SUB Rd, Rr
Сай 1 1 р ддддд рррр ADD / ADC Rd, Rr (LSL / ROL Rd, когда Rd = Rr)
1 р ддддд рррр CPSE Rd, Rr
1 р ддддд рррр И Rd, Rr
1 1 р ддддд рррр EOR Rd, Rr
1 1 р ддддд рррр ИЛИ Rd, Rr
1 1 1 р ддддд рррр MOV Rd, Rr
1 1 KKKK дддд KKKK ИПЦ Rd, тыс.
1 opc KKKK дддд KKKK Регистр-немедленные операции
1 c̅y̅ KKKK дддд KKKK SBCI / SUBI Rd, K
1 1 KKKK дддд KKKK ORI Rd, K SBR Rd, K
1 1 1 KKKK дддд KKKK ANDI Rd, K CBR Rd, K
1 k кк s ддддд y ккк LDD / STD Rd через Z + k или Y + k
1 1 s ддддд код операции Загрузка / сохранение операций
1 1 s ддддд LDS rd, i / STS i, rd
16-битный немедленный адрес SRAM i
1 1 s ддддд y 1 LD / ST Rd через Z + / Y +
1 1 s ддддд y 1 LD / ST Rd через −Z / −Y
1 1 ддддд 1 q LPM / ELPM Rd, Z
1 1 ддддд 1 q 1 LPM / ELPM Rd, Z +
1 1 1 ддддд 1 XCH Z, Rd
1 1 1 ддддд 1 1 LAS Z, Rd
1 1 1 ддддд 1 1 LAC Z, Rd
1 1 1 ддддд 1 1 1 LAT Z, Rd
1 1 s ддддд 1 1 LD / ST Rd через X
1 1 s ддддд 1 1 1 LD / ST Rd через X +
1 1 s ддддд 1 1 1 LD / ST Rd через −X
1 1 s ддддд 1 1 1 1 POP / PUSH Rd
1 1 1 ддддд код операции Инструкции с одним операндом:
1 1 1 ддддд COM Rd
1 1 1 ддддд 1 NEG Rd
1 1 1 ддддд 1 SWAP Rd
1 1 1 ддддд 1 1 INC Rd
1 1 1 ддддд 1 (зарезервированный)
1 1 1 ддддд 1 1 ASR Rd
1 1 1 ддддд 1 1 ЛСР Роуд
1 1 1 ддддд 1 1 1 ROR Rd
1 1 1 BBB 1 Бит сброса / установки регистра состояния SEx / CLx
1 1 1 1 код операции 1 Инструкции с нулевым операндом
1 1 1 1 1 RET
1 1 1 1 1 1 РЕТИ
1 1 1 1 1 Икс 1 (зарезервированный)
1 1 1 1 1 Икс Икс 1 (зарезервированный)
1 1 1 1 1 1 СПАТЬ
1 1 1 1 1 1 1 ПЕРЕРЫВ
1 1 1 1 1 1 1 WDR
1 1 1 1 1 1 1 1 (зарезервированный)
1 1 1 1 1 1 q 1 LPM / ELPM
1 1 1 1 1 1 1 1 SPM
1 1 1 1 1 1 1 1 1 SPM Z +
1 1 1 c е 1 1 Косвенный переход / вызов в Z или EIND: Z
1 1 1 ддддд 1 1 DEC Rd
1 1 1 кккк 1 1 1 DES раунд k
1 1 1 ккккк 1 1 c k JMP / CALL abs22
ккккккккккккккк
1 1 1 1 кк pp кккк ADIW Rp, uimm6
1 1 1 1 1 кк pp кккк SBIW Rp, uimm6
1 1 1 B ааааа BBB CBI / SBI a, b (сброс / установка бита ввода / вывода)
1 1 1 B 1 ааааа BBB SBIC / SBIS a, b (битовый тест ввода / вывода)
1 1 1 1 р ддддд рррр MUL, без знака: R1: R0 = Rr × Rd
1 1 1 s аа ддддд аааа ВХОД / ВЫХОД в пространство ввода / вывода
1 1 c 12-битное смещение со знаком RJMP / RCALL к ПК + simm12
1 1 1 KKKK дддд KKKK LDI Rd, K
1 1 1 1 7-битное смещение со знаком BBB Условный переход по биту регистра состояния
1 1 1 1 1 s ддддд BBB Бит регистра BLD / BST в STATUS.T
1 1 1 1 1 1 B ддддд BBB SBRC / SBRS пропускает, если бит регистра равен B
1 1 1 1 1 Икс Икс ддддд 1 BBB (зарезервированный)

Программирование микроконтроллеров pic на языке c

Теперь, наконец-то займемся делом после устанровок программ. Пора написать первую простенькую программу для микроконтроллера. Пережде чем мы начнем ее писать, надо поговорить о том, а какой МК мы будем использовать.

Я могу предложить хорошо зарекомендовавший себя МК PIC16F877. Он включает в себя практически все мыслимые и немыслимые интерфейсы и технологии (за исключением, пожалуй, только USB) и очень неплох по рабочим характеристикам:

Итак, с МК определились. В файлах к этой статье можно найти полный справочник по этому МК. Что покупать теперь понятно, но пока дайвайте все же напишем программу, что бы было понятно что с ней дальше делать и как ее «зашить» в этот МК.

В выпавшем списке доступных МК выбираем PIC16F877. Нажимаем Далее.

Здесь надо выбрать компилятор, который будет обрабатывать код нашей программы. Обязательно надо выбрать пункт HI-TECH PICC Toolsuite в выпадающем списке Active Toolsuite. Это тот самый компилятор языка Си, который мы установили в прошлой стаье. Нажимаем Далее.

Здесь можно добавить к проекту какие-либо готовые файлы, но нам пока такая возможность не нужна. Жмем Далее.

Тут я думаю все понятно. Нажимаем Готово.

Теперь помещаем ниже следующий код в открытое окно файла проекта TestPIC.c (весь проект целиком можно найти в файлах к этой статье).

Наверное Вам интересно, что будет результатом работы этого кода. Будет происходить следующее: к МК подключаются 8 светодиодов. При включении питания, светодиоды начнут мигать в виде «волны» (это лучше видеть, благо осталось нет так уж и много). Рассмотрим поподробнее сам код.

Что они означают? Давайте по порядку.

Дополнительные способы присваивания

Кроме простого оператора присваивания «=», в языке программирования С существует еще несколько комбинированных операторов присваивания: «+=», «-=», «*=<«, «/=», «%=». Рассмотрим типичные примеры их использования.

m += n; // то же, что и m = m + n; — сложить m и n // и поместить результат в переменную m

m -= n; // то же, что и m = m — n; — отнять от m значение n // и поместить результат в переменную m

m *= n; // то же, что и m = m * n; — умножить m на n // и поместить результат в переменную m

m /= n; // то же, что и m = m / n; — разделить m на n // и поместить результат в переменную m

m %= n; // то же, что и m = m % n; // вычислить целочисленный остаток от деления m на n// и поместить результат в переменную m

LCD_GoToXY()

  • Description  :This function moves the Cursor to specified position
  • I/P Arguments: char row,char col
    • row -> line number(line1=0, line2=1),For 2line LCD the I/P argument should be either 0 or 1.
    • col -> char number.For 16-char LCD the I/P argument should be betwen 0-15.
  • Return value : none
void LCD_GoToXY(char row, char col)
{
   char pos;
 
    if(row<LCDMaxLines)
      {
		 pos= LineOne | (row << 6); // take the line number
		                            //row0->pos=0x80  row1->pos=0xc0
 
	    if(col<LCDMaxChars)
		   pos= pos+col;            //take the char number
		                            //now pos points to the given XY pos
 
		 LCD_CmdWrite(pos);	       // Move the Cursor to specified Position
       }
}

________________________________________________________

   Для каждого типа микроконтроллера есть свой заголовочный файл. Для ATMega8535 этот файл называется iom8535.h, для ATMega16 – iom16.h. По идее мы должны в начале каждой программы подключать заголовочный файл того микроконтроллера, который мы используем.  Умные люди немного облегчили нам жизнь и написали заголовочный файл ioavr.h. Препроцессор обрабатывает этот файл и в зависимости от настроек проекта включает в нашу программу нужный заголовочный файл. Итак, следущая строчка программы #include <ioavr.h>    В нашей программе мы будем использовать задержку. Задержку можно реализовать программно и аппаратно. Сейчас нас интересует программная задержка. IAR содержит библиотеку, в которой уже есть готовая функция задержки. Нам нужно подключить к нашей программе эту библиотеку. Как это сделать? Каждая библиотека имеет свой заголовочный файл в котором описано какие фукции она содержит. Этот файл мы и должны включить в программу. Делается это, как вы догадались с помощью директивы #include.#include <intrinsics.h>       Основу любой сишной программы составляют функции, и любая  программа на Си имеет хотя бы одну функцию – main().Вообще-то на примере main() не хотелось бы объяснять синтаксис функций, потому что main() хоть и является функцией, но вызывается не как обычно, а автоматически. С этой функции микроконтроллер начинает выполнение написанной нами программы. Вызовы всех других функций, наших или библиотечных, должны быть записаны в коде. Как вызывается функция, мы увидим дальше.У функции есть заголовок – int main(void) и тело – оно ограниченно фигурными скобками {}. В тело функции  мы и будем добавлять наш код.