Есть два камня связанных по uart. Первый снимает значения с АЦП, порта RD и отправляет пакет данных, который представляет собой четыре байта по uart на скорости 9600. Указывается начало пакета и его конец ввиде четырех битов соответственно. Сбор значений и отправка пакета происходит нормально. Но прием не работает вообще и никак. Камни используютя для передачи 16F877и для приема 16F628a.
Внимание! Код хоть и ламерский но много!
Приемник:
Передатчик:
Суть следующая. При приеме проверяется флаг RCIF, если присутствует, читаем RCREG и смотрим что нам за байт пришел. Если пакет не пришел в указанное время то включаем так назваемый Safe Mode(по сути, сбрасываем данные на дефолт). В даташите как бы указано, что при чтении RCREG флаг RCIF сбрасывается аппаратно. Но чет код вообще нифига не пашет(. Прерывание не использую т.к. там своих прерываний хватает, еще сдесь вырезал функции записи EEPROM, опроса датчиков, отправки данных другим абонентам etc.
Какие у вас есть мысли?
Внимание! Код хоть и ламерский но много!
Приемник:
Спойлер
Код: Выделить всё
#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; //сброс флага
}
}
Какие у вас есть мысли?
- Вложения
-
- code.rar
- (4.78 КБ) 173 скачивания
