Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2731

.pdf
Скачиваний:
0
Добавлен:
15.11.2022
Размер:
2.16 Mб
Скачать

Программная часть проекта разработана с использованием компилятора Keil C51. Исходный текст программы:

#include <stdio.h> #include <REG52.H> sbit CS = P1^0;

sbit SCK = P1^1; sbit SO = P1^2; unsigned int temp; unsigned int cnt; void delay(void)

{

unsigned int i1 = 5; while(i1 != 0)i1—;

}

unsigned int getTemp(void)

{

temp = 0; P1 = 0xFC; CS = 1;

CS = 0; delay();

for (cnt = 0; cnt < 16; cnt++)

{

SCK = 0; delay(); temp |= SO;

temp = temp<<1; SCK = 1;

}

CS = 1;

temp = temp>>3; temp &= 0xFFF; return temp;

71

}

void main(void)

{

float ft1; SCON = 0x50; TH1 = 0xFD; TMOD |= 0x20; TR1 = 1;

TI = 1; while (1)

{

ft1 = getTemp() * 1024.0 / 4096.0; printf(“Current temperature: %6.1f\n“, ft1); printf(“Press Enter to continue...\n“); getchar();

}

}

Программа ожидает нажатия клавиши на консоли удаленного терминала, после чего выводит в последовательный порт значение температуры, измеренной с помощью термопары. Параметры обмена по последовательному порту рассчитаны для скорости 9600 бод при тактовой частоте 11,059 МГц.

Прием данных по интерфейсу SPI осуществляется в цикле for функции getTemp. Счетчик цикла cnt для упрощения принимает значения от 0 до 15, после чего 16-разрядное значение температуры, сохраненное в переменной temp, корректируется так, чтобы отсечь ненужные биты D15, D2 – D0. Это выполняется следующим фрагментом программного кода:

temp = temp>>3; temp &= 0xFFF;

В данном проекте используется интерфейс SPI, в котором обмен данными осуществляется в одном направлении,

72

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

Вследующем проекте интерфейс SPI используется как для записи, так и для считывания данных в/из устройства, причем ведущим, как и в рассмотренном измерителе температуры, является микроконтроллер 8052.

Вэтом проекте будет продемонстрирован обмен данными по протоколу SPI с микросхемой перепрограммируемой памяти (EEPROM) 25C320 с объемом памяти 32 Кбит. Принципиальная схема аппаратной части показана на рис. 3.8.

Рис. 3.8. Схема обмена данными с памятью по протоколу SPI

73

Несколько слов о принципах функционирования микросхемы 25C320. Микросхема памяти содержит 8- разрядный регистр команд. Считывание данных из устройства осуществляется через вывод SO по фронту сигнала SCK, при этом сигнал CS должен иметь низкий уровень, а вывод HOLD – высокий. Вывод WP при выполнении операций записи должен иметь высокий уровень, при низком уровне микросхема защищена от записи.

Обмен данными по протоколу SPI осуществляется от старшего значащего бита (MSB), который идет первым, к младшему (LSB). При записи биты данных на линии SI записываются в микросхему по фронту сигнала SCK при низком уровне сигнала CS. При высоком уровне на линии CS прием/передача данных в/из EEPROM невозможны.

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

Проанализируем, как выполняется чтение данных из микросхемы памяти, для чего обратимся к рис. 3.9.

Рис. 3.9. Временная диаграмма чтения данных из микросхемы

74

Устройство выбирается при установке сигнала CS в низкий уровень. Вначале передается команда чтения READ (ее код равен 3), затем 16$разрядный адрес, старшие 4 бита которого игнорируются. Если команда чтения выполнена корректно и установлен корректный адрес, то считываемые данные бит за битом появляются на выводе SO. При этом данные, находящиеся по следующим адресам, могут считываться при подаче последующих синхроимпульсов, поскольку внутренний указатель адреса в микросхеме памяти автоматически инкрементируется после передачи байта данных в микроконтроллер. По достижении адреса 0xFFF следующее значение указателя станет 0x000, и цикл чтения продолжится. Операция чтения, как и другие, заканчивается при установке сигнала CS в высокий уровень. Последовательность операций при записи данных несколько иная, чем при чтении. Прежде всего, перед выполнением операции записи данных в микросхему 25C320 необходимо разрешить запись данных, выполнив команду WREN (рис. 3.10).

Рис. 3.10. Разрешение записи данных

Как обычно, вначале устанавливаем сигнал CS в низкий уровень, после чего бит за битом отправляем команду WREN (ее код равен 6) в EEPROM. По окончании записи команды

75

обязательно следует установить сигнал CS в высокий уровень. Если этого не сделать, то следующая за данной командой запись данных не выполнится, поскольку регистр-защелка не будет установлен должным образом. Обратите внимание на то, что линия SO должна находиться в высокоимпедансном состоянии.

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

Рис. 3.11. Запись байта данных в микросхему памяти

Запись байта данных начинается с установки сигнала CS в низкий уровень, после чего на линию SI выталкиваются биты команды WRITE (код равен 2). Немедленно после команды микроконтроллер должен выставить 16-разрядный адрес ячейки памяти, затем байт данных для записи. Цикл записи байта в память заканчивается при установке сигнала CS в высокий уровень. Сигнал CS должен устанавливаться только после записи младшего бита данных, иначе операция записи будет неудачной.

Установка сигнала CS, тем не менее, не означает окончания внутренних операций микросхемы по записи данных. Вполне возможно, что операция записи фактически будет продолжаться еще некоторое время. В этом случае перед выполнением чтения байта следует проверить бит 0 регистра состояния EEPROM.

76

Регистр состояния имеет поля, изображенные на рис. 3.12.

Рис. 3.12. Регистр состояния микросхемы

Бит WIP (Write-In-Process) показывает, выполняет ли устройство 25С320 операцию записи. Если бит установлен в 1, то операция записи выполняется, если в 0, то операция закончилась. Этот бит устанавливается логикой микросхемы и доступен только для чтения. Прочитав этот бит, программа определяет, когда можно выполнить следующую операцию, например, чтение только что записанного байта.

Бит WEL (Write Enable Latch) показывает состояние регистра-защелки записи. Если бит установлен в 1, регистрзащелка разрешает запись данных, если установлен в 0, то запись запрещена. Состояние этого бита можно обновить, выполнив либо команду WREN (разрешение записи), либо команду WRDI (запрет записи).

По окончании цикла записи регистр-защелка сбрасывается. Биты BP0 и BP1 показывают, какие блоки памяти являются защищенными, и устанавливаются командой

WRSR.

Программа может прочитать регистр состояния с помощью команды RDSR (ReaD Status Register). Временная диаграмма показана на рис. 3.13.

77

Рис. 3.13. Временная диаграмма цикла чтения регистра состояния

Цикл чтения регистра состояния начинается с установки сигнала CS в низкий уровень, после чего на линию SI побитово выводится команда RDSR (код равен 5). Вывод битов команды выполняется синхронно с импульсами 0–7 CLK, после чего на линию SO выводится бит за битом байт статуса, который считывается микроконтроллером. Завершается цикл чтения регистра состояния установкой сигнала CS в высокий уровень.

Рассмотрим программный код, демонстрирующий запись/чтение одного байта в/из EEPROM 25С320. Алгоритм работы программы таков:

-по команде WREN разрешается запись данных в микросхему памяти;

-по команде WRITE байт данных записывается по указанному адресу в памяти;

-программа ожидает завершения операции записи, периодически анализируя бит 0 регистра состояния (используется команда RDSR);

78

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

Программа написана на Keil C51, и ее исходный текст показан ниже:

#include <stdio.h> #include <intrins.h> #include <REG52.H> #define WREN 0x6 #define WRITE 0x2 #define READ 0x3 #define RDSR 0x5 #define ADDR 0x2 sbit CS = P1^0;

sbit SCK = P1^1; sbit SI = P1^2; sbit SO = P1^3;

unsigned char byteRead; unsigned char Cmd; unsigned int Addr; unsigned int cnt;

void delay(unsigned int d1)

{

while(d1 != 0)d1—;

}

void shift_out8(unsigned char c1)

{

for (cnt = 0; cnt < 8; cnt++)

{

SCK = 0; delay(20);

c1 = _crol_(c1, 1); SI = c1 & 0x1; delay(2);

79

SCK = 1; delay(20);

}

}

void shift_out16(unsigned int i1)

{

for (cnt = 0; cnt < 16; cnt++)

{

SCK = 0; delay(20);

i1 = _irol_(i1, 1); SI = i1 & 0x1; delay(2);

SCK = 1; delay(20);

}

}

unsigned char shift_in8(void)

{

unsigned char t1; t1 = 0;

for (cnt = 0; cnt < 9; cnt++)

{

SCK = 0; delay(10000); t1 = t1<<1; t1 |= SO;

SCK = 1; delay(10);

}

return t1;

}

unsigned char readByte(void)

{

CS = 1;

80

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]