Внимание! Код хоть и ламерский но много!
Приемник:
Спойлер
Код: Выделить всё
#include <pic.h>
__CONFIG(HS & WDTDIS & PWRTDIS & BORDIS & LVPDIS & UNPROTECT); //биты камня(они же фьюзы в avr)
//Пакет данных
unsigned char StartByte; //Первый байт
unsigned char ADCbyte; //Второй байт
unsigned char ServoByte; //Третий байт
unsigned char StopByte; //Четвертый байт
unsigned char NumOfByte; //Порядок байтов
//Пакет данных
//Сервопривод
static volatile unsigned int num @ 0x26; // ширина импульса
static volatile unsigned char numL @ 0x26; // ширина импульса младший
static volatile unsigned char numH @ 0x27; // ширина импульса старший
short int delay;
short int dTime;
//Сервопривод
unsigned char error;
unsigned char ErrorMode;
unsigned char Tbyte;
unsigned char temp;
void init (void){
CMCON = 0x07; //Отключаем компараторы.
TRISA = 0b00000000; //Порт А - на выход.
TRISB = 0b00000110; //Порт В - на выход, пины RB3/RB2 которые принадлежат RX/TX
PORTA = 0; //далее - очищаем порты.
PORTB = 0;
// UART
// TXSTA : CSRC TX9 TXEN SYNC --- BRGH TRMT TX9D
TXSTA=0b00100000; // Asynch,8bits,tx enb
// RCSTA : SPEN RX9 SREN CREN ADEN FERR OERR RX9D
RCSTA=0b10010000; // Cont receive enb
SPBRG=32; // asinhron BRGH=0 ->32;BRGH=1 ->129 for 9600
OPTION = 0b10000111; //Конфигурация переферии по умолчанию, предделитель таймера 0 на 256
INTCON = 0b11100000; //Конфигурация прерываний
T0IF = 0; //Сбрасываем флаг таймера 0
CCP1CON = 0b00001100; //Настройка ШИМ канала RC2
CCPR1L = 0b0000000; //Начальная скважность импульсов 0%
T2CON = 0b00000101; //Таймер 2 - включен, 1:4
TMR2 = 0; //Таймер 2 - стартуем с 0
PR2 = 0xFF; //Значение регистра периода таймера 2 для ШИМ генерации
T1CON = 0b00010001; // Настройка TMR1
TMR1IE = 1;
TMR1IF = 0;
//////////////////////////////////////////////////////////////////////
// Регистр настроек OPTION //
//RBPU = 1; //подтягивающие резисторы выкл бит 7 //
//INTEDG = 0; //прерывания по заднему фронту сигнала бит 6 //
//T0CS = 0; //внутренний тактовый сигнал таймера 0 бит 5 //
//T0SE = 0; //приращение по переднему фронту TMR0 бит 4 //
//PSA = 0; //предделитель включен перед TMR0 бит 3 //
//PS2 = 1; //установка бит 2 //
//PS1 = 1; //коэффициента бит 1 //
//PS0 = 1; //предделителя TMR0 на 256 бит 0 //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Регистр прерываний INTCON //
//GIE = 1; //разрешаем глобальные прерывания бит 7 //
//PEIE = 1; //разрешаем прерывания периферии бит 6 //
//T0IE = 1; //запрещаем прерывания по таймеру 0 бит 5 //
//INTE = 0; //запрещаем внешние прерывания бит 4 //
//RBIE = 0; //запрещаем прерывания по порту В бит 3 //
//T0IF = 0; //очищаем флаг таймера 0 бит 2 //
//INTF = 0; //очищаем флаг внешнего прерывания бит 1 //
//RBIF = 0; //очищаем флаг прерывания на порту В бит 0 //
//////////////////////////////////////////////////////////////////////
num = 61785;
NumOfByte = 0;
}
// UART
unsigned char getch_Usart(void) // Получение байта.
{
while(!RCIF) // Устанавливается, когда регистр не пуст.
continue;
return RCREG;
}
void send_Usart(unsigned char c) // Отправка байта.
{
while(TXIF!=1) // Устанавливается, когда регистр свободен.
{}
TXREG = c;
}
// -UART
void SafeMode(void) //Выполняем "Safe Mode".
{
CCPR1H = 0;
delay = 128;
RB7 = 0;
RB6 = 0;
RB5 = 0;
RB4 = 0;
RA3 = 0;
RA2 = 1;
RA1 = 0;
RA0 = 0;
error = 1; //Включаем сигнал об обрыве связи.
}
void LoadPacket (void) //Загружаем данные пакета.
{
if (NumOfByte == 4 ){
error = 0; //Отключаем сигнал об обрыве связи.
NumOfByte = 0;
CCPR1H = ADCbyte;
delay = ServoByte;
StartByte &= 0b00001111;
PORTB = StartByte;
StopByte &= 0b11110000;
PORTA = StopByte;
}
}
void ReceiveSetting()
{
}
void StartConfig()
{
}
void main (void)
{
init(); //Проходим конфигурацию.
StartConfig(); //Загружаем начальные значения из EEPROM.
while(1){
if(RCIF){
TMR0 = 0; //Обнуляем таймер ожидания пакета.
Tbyte = getch_Usart();
temp = Tbyte;
temp &= 0b11110000; //Проверяем, первый ли это байт пакета.
if (temp == 0b11010000) {
NumOfByte = 1; //Пришел 1й байт?
StartByte = Tbyte;
Tbyte = 0;
TMR0 = 0; //
} else { //Не совпадает со стартовым?
if (NumOfByte == 1 ){ //Пришел второй байт?
NumOfByte = 2;
ADCbyte = Tbyte;
goto exit; //Выходим из условия и ждем 3й байт.
}
if (NumOfByte == 2 ){
NumOfByte = 3; //Пришел третий байт?
ServoByte = Tbyte;
goto exit; //Выходим из условия и ждем 4й байт.
}
if (NumOfByte == 3 ){
temp = Tbyte;
temp &= 0b00001111;
if (temp == 0b00001101) { //Пришел стоп байт?
NumOfByte = 4;
StopByte = Tbyte;
LoadPacket(); //Пакет принят.
} else {
SafeMode(); //Пакет не принят.
}
goto exit; //Выходим из условия.
}
exit:
while (1 < 2) {
asm ("NOP");
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (temp == 0b10110000) {
NumOfByte = 1; //Пришел 1й байт?
StartByte = Tbyte;
Tbyte = 0;
TMR0 = 0; //
} else { //Не совпадает со стартовым?
if (NumOfByte == 1 ){ //Пришел второй байт?
NumOfByte = 2;
ADCbyte = Tbyte;
goto wait; //Выходим из условия и ждем 3й байт.
}
if (NumOfByte == 2 ){
NumOfByte = 3; //Пришел третий байт?
ServoByte = Tbyte;
goto wait; //Выходим из условия и ждем 4й байт.
}
if (NumOfByte == 3 ){
temp = Tbyte;
temp &= 0b00001111;
if (temp == 0b00001011) { //Пришел стоп байт?
NumOfByte = 4;
StopByte = Tbyte;
LoadPacket(); //Пакет принят.
} else {
SafeMode(); //Пакет не принят.
}
goto wait; //Выходим из условия.
}
wait:
while (1 < 2) {
asm ("NOP");
}
}
}
}
}
void interrupt pwm_int(void) // Общая процедура прерывания.
{
if (T0IF == 1)
{
if (error == 1) {
ErrorMode = ErrorMode + 1;
if (ErrorMode == 153) {
ErrorMode = 0;
RA2 = ~RA2;
}
}
SafeMode(); //Пакет данных не получен.
T0IF = 0;
}
if (TMR1IF) {
T0IE = 0; //Вырубаем первый таймер чтоб не сифонил по чем зря.
TMR1IF=0; // Сбрасываем флаг о его переполнении.
if (num < 61000){ //Ширина импульса.
delay = delay*10;
num = 61785+delay;
TMR1H = numH;
TMR1L = numL;
RB3 = 1;
} else { //50гц.
RB3 = 0;
dTime = 65535 - num;
num = 65535 - (50000 - dTime);
TMR1H = numH;
TMR1L = numL;
}
T0IE = 1; //Врубаем первый таймер.
}
}
Спойлер
Код: Выделить всё
#include <pic.h>
__CONFIG(HS & WDTDIS & PWRTDIS & BORDIS & LVPDIS & UNPROTECT); //биты камня(они же фьюзы в avr)
#define temp RB0 // temporary key for testing delay's
unsigned char StartByte; //Первый байт
unsigned char ADCbyte; //Второй байт
unsigned char ServoByte; //Третий байт
unsigned char StopByte; //Четвертый байт
unsigned char x;
short int delay;
void init (void){
CMCON = 0x07; //Отключаем компараторы
TRISA = 0b00001011; //Порт А - на вход, три канала АЦП RA0,RA1,RA3
TRISB = 0b00000000; //
TRISC = 0b11000000; //RC6, RC7, которые принадлежат uart
TRISD = 0b11111111;
TRISE = 0b00000000;
PORTA = 0; //далее - очищаем порты
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;
// 76543210
// TXSTA : CSRC TX9 TXEN SYNC --- BRGH TRMT TX9D
TXSTA=0b00100000; // Asynch,8bits,tx enb
// RCSTA : SPEN RX9 SREN CREN ADEN FERR OERR RX9D
RCSTA=0b10010000; // Cont receive enb
SPBRG=32; // asinhron BRGH=0 ->32;BRGH=1 ->129 for 9600
OPTION = 0b10000111; //Конфигурация переферии по умолчанию, предделитель таймера 0 на 128
INTCON = 0b01100000; //Конфигурация прерываний
ADCON0 = 0b00000001; //Конфигурация АЦП
ADCON1 = 0b00000100;
//////////////////////////////////////////////////////////////////////
// Регистр настроек OPTION //
//RBPU = 1; //подтягивающие резисторы выкл бит 7 //
//INTEDG = 0; //прерывания по заднему фронту сигнала бит 6 //
//T0CS = 0; //внутренний тактовый сигнал таймера 0 бит 5 //
//T0SE = 0; //приращение по переднему фронту TMR0 бит 4 //
//PSA = 0; //предделитель включен перед TMR0 бит 3 //
//PS2 = 1; //установка бит 2 //
//PS1 = 1; //коэффициента бит 1 //
//PS0 = 0; //предделителя TMR0 на 256 бит 0 //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Регистр прерываний INTCON //
//GIE = 1; //разрешаем глобальные прерывания бит 7 //
//PEIE = 1; //разрешаем прерывания периферии бит 6 //
//T0IE = 1; //разрешаем прерывания по таймеру 0 бит 5 //
//INTE = 0; //запрещаем внешние прерывания бит 4 //
//RBIE = 0; //запрещаем прерывания по порту В бит 3 //
//T0IF = 0; //очищаем флаг таймера 0 бит 2 //
//INTF = 0; //очищаем флаг внешнего прерывания бит 1 //
//RBIF = 0; //очищаем флаг прерывания на порту В бит 0 //
//////////////////////////////////////////////////////////////////////
}
// UART
unsigned char getch_Usart(void)// Получение байта
{
while(!RCIF) // Устанавливается, когда регистр не пуст.
continue;
return RCREG;
}
void send_Usart(unsigned char c) // Отправка байта
{
while(TXIF!=1) // Устанавливается, когда регистр свободен
{}
TXREG = c;
}
// -UART
void main (void)
{
init(); //проходим конфигурацию
while(1) {
temp = 1;
StartByte = 0b11010000;
StopByte = 0b00001101;
ADCON0 = 0b00000001; // обрабатываем значение оси Z(акселерометр), канал ацп RA1
delay = 0;
while (delay < 10) { //Задержка АЦП
delay = delay + 1;
}
ADGO = 1;
while (ADGO == 1) {
asm("NOP");
}
ADCbyte = ADRESH; //Значения из АЦП отправляем в переменную Z
ADCON0 = 0b00001001; // обрабатываем значение оси X(вперед - назад), канал ацп RA2
delay = 0;
while (delay < 10) { //Задержка АЦП
delay = delay + 1;
}
ADGO = 1;
while (ADGO == 1) {
asm("NOP");
}
x = ADRESH; //Значения из АЦП отправляем в переменную X
if (x < 130) { //Устанавливаем ноль на центре манипулятора Х(+/- 2 значения погрешности)
if (x > 126) {
StopByte &= 0b00111111; //Вперед и назад выкл.
}
}
if (x > 130 ) {
StopByte |= 0b10000000; //Вперед
}
if (x < 126 ) {
StopByte |= 0b01000000; //Назад
}
ADCON0 = 0b00011001; // обрабатываем значение оси Y(импульс сервопривода), канал ацп RA3
delay = 0;
while (delay < 10) { //Задержка АЦП
delay = delay + 1;
}
ADGO = 1;
while (ADGO == 1) {
asm("NOP");
}
ServoByte = ADRESH; //Значения из АЦП отправляем в переменную ServoByte
if (RD0 == 1) {
StartByte |= 0b00000001;
}
if (RD1 == 1) {
StartByte |= 0b00000010;
}
if (RD2 == 1) {
StartByte |= 0b00000100;
}
if (RD3 == 1) {
StartByte |= 0b00001000;
}
if (RD4 == 1) {
StopByte |= 0b00010000;
}
if (RD5 == 1) {
StopByte |= 0b00100000;
}
send_Usart(StartByte); //Первый байт
send_Usart(ADCbyte); //Второй байт
send_Usart(ServoByte); //Третий байт
send_Usart(StopByte); //Второй байт
////////////////////////////////////////////////////////////////////////////
temp = 0;
delay = 0;
while (delay < 150) { //Мертвое время проца
delay = delay + 1;
}
}
}
void interrupt pwm_int(void) // общая процедура прерывания
{
if (T0IF == 1)
{
TMR0 = 60; //10 мсек на тик
T0IE = 0; //Отключаем таймер
T0IF = 0; //Сбрасываем флаг
T0IE = 1; //Включаем таймер
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
if (TMR2IF == 1) //таймер 2
{
TMR2IF = 0; //сброс флага
}
}
Какие у вас есть мысли?
