А оказалось что DRS516 стал по каким - то причинам глухим. Купил новый, подключил - заработало!
Схема передающей части.
Трансформатор от какой - то вч-шняги. Это некритично. Индуктивность 1мГн.
Zero_Cross.
Работает на 2 внешних прерывания AT91sam7s 256. Дело в том, что процессор должен реагировать на оба фронта сигнала, а настроить можно только один. В итоге удалось вытянуть Zero_Cross из DRS - 516 и сравнить осциллографом.
Вот что получилось:
В разработках я опирался на AN236 от Микрочип. Софт делал строго по протоколу. Помог осциллограф DSO-5200A. У него буфер 1M, что позволило записать всю передаваемую от DRS - 516 посылку и ее проанализировать. Если отойти от протокола, прграмму можно сильно упростить.
Софт. Настраиваем внешние прерывания:
Код
//Внешнее прерывание
*AIC_SMR30 = (1 << 5) |(1 << 6)| 7; //Задний фронт(5), передний фронт (5,6)
*AIC_SVR30 = (unsigned long) EXT0_int; //7-й уровень пиоритета (IRQ0) Стр.165. PA20, P3.4
*AIC_SMR31 = (1 << 5) | 6; //Задний фронт(5), передний фронт (5,6)
*AIC_SVR31 = (unsigned long) EXT1_int; //7-й уровень пиоритета (IRQ1) Стр.165. PA30, P2.6
*AIC_IECR = 0xC0000000; //Разрешить внешнее прерывание
И пишем их код:
Код
__irq void EXT0_int(void) { //Внешнее прерывание. Начало и остановка измерений АЦП
ZeroCross = 1; //
__irq void EXT1_int(void) {ZeroCross = 1; *AIC_EOICR = 1;}
Сам обработчик X10:
Код
extern int ZeroCross;
//Функции X10
void Pulse1ms(void); //Передача импульса в сеть
void Pulse1ms1(void); //Генератор импульса 120КГц 1мс
void Pause1ms(void); //Генератор паузы 1мс
void WaitZC (void); //Ожидание события - перехода синосоиды 50Гц через 0.
void SendStart(void); //Передача старт - условия: три единичные посылки 1мс и пауза 1мс
void Trnsfer (unsigned char DATA, int Bits); //Педача данных длиной Bits в сеть
void SendX10Command (int House, int Unit, int Command){//Педача команды в сеть
SendStart(); //Передаем посылку 1110
Trnsfer(House,4); //House. 0110 = A
Trnsfer(Unit,5); //Unit Addresses = 00110 = 1
SendStart(); //Передаем посылку 1110
Trnsfer(House,4); //House. 0110 = A
Trnsfer(Unit,5); //Unit Addresses = 00110 = 1
WaitZC(); //Пропускаем 6 переходов
WaitZC(); //через 0.
WaitZC(); //
WaitZC(); //
WaitZC(); //
WaitZC(); //
SendStart(); //Первый раз
Trnsfer(House,4); //House. 0110 = A
Trnsfer(Command,5); //On = 10100
SendStart(); //Второй раз.
Trnsfer(House,4); //House. 0110 = A
Trnsfer(Command,5); //On = 10100
}
//Для DRS-16 достаточно такого алгоритма:
/* SendStart(); //
Trnsfer(6,4); //House
Trnsfer(0x1c,5); //Unit / Function. Function = On
*/
//--------------------------------------------------------------------------------------------------------------------
void Trnsfer (unsigned char DATA, int Bits){//Педача данных длиной Bits в сеть
unsigned char i; //
unsigned char mask; //
for(i=0; i<Bits; i++) { //
mask = (1 << i); //Выделение передаваемого бита
WaitZC(); //Ожидание перехода через 0 перед передачей бит - интервала
if((DATA&mask) == 0) //Передача 0:
{Pause1ms(); //
WaitZC(); //Ожидание перехода через 0 между полубитным интервалом
Pulse1ms();} //
else //Передача 1:
{Pulse1ms(); //1
WaitZC(); //Ожидание перехода через 0 между полубитным интервалом
Pause1ms();} //
} //for(i=0; i<Bits; i++)
} //void Trnsfer (unsigned char DATA, int Bits)
//--------------------------------------------------------------------------------------------------------------------
void WaitZC(void) { //Ожидание события - перехода синосоиды 50Гц через 0.
ZeroCross = 0; //
while(!ZeroCross) {} //
} //
//--------------------------------------------------------------------------------------------------------------------
void SendStart(void){ //Передача старт - условия: три единичные посылки 1мс и пауза 1мс
WaitZC(); //Ожидание перехода через 0
Pulse1ms(); //
WaitZC(); //Ожидание перехода через 0
Pulse1ms(); //
WaitZC(); //Ожидание перехода через 0
Pulse1ms(); //
WaitZC(); //Ожидание перехода через 0
Pause1ms(); //Передача паузы необязательна
}
//--------------------------------------------------------------------------------------------------------------------
void Pulse1ms (void){ //Передача импульса. Импульс передается 3 раза
Pulse1ms1(); //со слвигом 120градусов для трех разных фаз. Фаза A
Pause1ms(); //
Pause1ms(); //
Pulse1ms1(); //Фаза B
Pause1ms(); //
Pause1ms(); //
Pulse1ms1();} //Фаза C
//Хотя для DRS516 фазы B и С не нужны. И так работает. Достаточен вызов только Pulse1ms1()!
//--------------------------------------------------------------------------------------------------------------------
//Передача единичной посылки длительностью 1мс с помощью ШИМ. Частота заполнения 120КГц.
//Длительность посылки задается с помощью таймера TC1.
//Таймер запрограммирован на останов по совпадению с RC. Загружаем RC нужной величиной
//и ждем бита совпадения таймера TC1_CV с RC(бит CPCS, поз4, стр 414). При совпадении
//таймер автоматически останавливается.
void Pulse1ms1 (void){ //Генератор импульсов 120КГц 1мс
*TC1_RC = 28000; //28000
*PWM_ENA = 1; //Разрешить работу канала PWM1 (CHID0), P0.3, 120КГц.
*TC1_CCR = 0x5; //Запустить таймер 1 + SWTRG=1
while (!(*TC1_SR&(1<<4))) {} //Ждать 1мс до совпадения регистра таймера TC1_CV с RC
*PWM_DIS = 1; //120КГц. Запретить работу канала PWM1 (CHID0), P0.3
*TC1_CCR = 0x6;} //Остановить таймер
//--------------------------------------------------------------------------------------------------------------------
void Pause1ms (void){ //Генератор паузы 1мс
*TC1_RC = 25000; //25000
*TC1_CCR = 0x5; //Запустить таймер 1 + SWTRG=1
while (!(*TC1_SR&(1<<4))) {} //Ждать 1мс до совпадения регистра таймера TC1_CV с RC
*TC1_CCR = 0x6;} //Остановить таймер
//DRS516 срабатывает при значениях TC1_RC от 1000 до 800 000
И его вызов:
Код
if (Knob) { //
int House = 0xc; //House = K
int Unit = 5; //
int Command; //OFF = 0x1c, ON = 0x14, All Units Off = 0x10, All Units On = 0x18
if (Knob<3) {Command = 0x14;}
else {Command = 0x1c;}
SendX10Command(House, Unit, Command);
Knob = 0; //
}
DRS-516 удалось запрограммировать на новый House и Unit код.