В данной статье рассматриваются азы программирования микроконтроллеров на Си. Язык программирования Си — высокоуровневый язык, основной идеей которого является работа с функциями, аргументы которых передаются как параметры. Любая функция состоит из имени и скобок с аргументами. Аргументы разделяются запятыми. Основное тело программы заключено в функцию main(). Любая программа должна содержать эту функцию т.к. с неё начинается работа программы.
Расмотрим пример простой программы для микроконтроллера AVR для компилятора WinAVR:
{codecitation class=»brush: vb; gutter: true;» width=»700px» }
#include <avr/io.h>
#define F_CPU = 1000000UL;
#include <util/delay.h>
int main(void){
DDRD = 0b00000100; // второй бит порта D — выход, остальные входы
while(1){
PORTD ^= 0b00000100; // исключающее или — сменить состояние второго бита
_delay_ms(250); // ожидание 250 мс
}
return 0;
}
{/codecitation}
В этой программе содержатся основные элементы языка.
Все препроцессорные команды начинаются со знака «#».
{codecitation class=»brush: vb; gutter: true;» width=»700px» }
#include <avr/io.h> — препроцессорная команда которая подключает библиотеку аппаратных описаний микроконтроллера. В ней содержатся аппаратные адреса портов и регистров микроконтроллера. Используя эту библиотеку можно использовать легкозапоминающиеся мнемоники такие как: DDRD, PORTD, TCNT0, MCUCR… а не их адреса, которые не так легко запомнить. Например, ресли рассмотреть файл io.h для микроконтроллера ATtiny13:
…
/* Timer/Counter0 (8-bit) */
#define TCNT0 _SFR_IO8(0x32)
/* Timer/Counter 0 Control Register B */
#define TCCR0B _SFR_IO8(0x33)
# define FOC0A 7
# define FOC0B 6
# define WGM02 3
# define CS02 2
# define CS01 1
# define CS00 0
…
{/codecitation}
Заметить, что адресу регистра Timer0 присваивается легкозапоминаемая мнемоника TCNT0.Поэтому в своей программе мы можем писать так:
{codecitation class=»brush: vb; gutter: true;» width=»700px» }
TCCR0B |=(0<<CS02)|(1<<CS01)|(1<<CS00); // устанавливаем коэффициент
// деления тактовой частоты
TCNT0 = 239; // фактически записываем значение в регистр с адресом 0x32
DDRB |=(1<<1)|(1<<2); // Делаем выходами первый и второй бит порта B (он же регистр ввода/вывода с адресом 0x17)
{/codecitation}
Если файл *.h заключен в двойные кавычки, то поиск файла проводится в папке проекта.
{codecitation class=»brush: vb; gutter: true;» width=»700px» }
#define F_CPU = 1000000UL; //указывает компилятору, что наш кристал тактируется от резонатора с тактовой частотой в миллиор герц т.е. 1МГц. «UL» — после числа показывает, что число Unsigned Long т.е. беззнаковое типа «long»
{/codecitation}
{codecitation class=»brush: vb; gutter: true;» width=»700px» }
int main(void) — означает, что функция main возвращает значение типа int т.е. значения от 0 до 65535.
{/codecitation}
Открывающаяся фигурная скобка “{” показывает начало исполняемой части функции.
{codecitation class=»brush: vb; gutter: true;» width=»700px» }
while(1){…} — бесконечный цикл, код заключенный в фигурные скобки будет выполняться бесконечно.
{/codecitation}
«//» — символы начала комментария, текст в строке после этих символов не включается в программу при компиляции.
«Return 0» — возвращает значение функции main(). Все функции должны заканчиваться закрывающимися фигурными скобками «}. После каждой команды надо ставить «;».
Основные типы данных:
Тип | Название | Размер в битах | Диапазон значений |
char | Символ | 8 | -128…127 |
int | Целое число | 16 | -32768…32767 |
float | Вещественное число | 32 | ±10-38…±3*1038 |
long int | Длинное целое | 32 | ±2147483647 |
unsigned char | ASCII символ | 8 | 0…255 |
unsigned int | Беззнаковое целлое | 16 |
0…65535 |
2 комментария
А это тоже код на Си?
{codecitation class=”brush: vb; gutter: true;” width=”700px” }
обалденный код Си
{codecitation class=”brush: vb; gutter: true;” width=”700px” }
а что это за тактовая частота в «миллиор» герц
обалденное название «Беззнаковое целлое», может надо три «л»
а не кажется, что в слове «кристал» одно «л» не хватает?