АСВТ 2 семестр ЛР №8

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 18:08, 13 мая 2016.


UART на PIC12F675. Использование отладочной платы AX-12

Работа с UART

Цель работы. Научиться работать с UART на МК PIC12F675[1].

Пример 1

Исходные данные. Осуществить общение двух МК с помощью UART. Скорость передачи данных, контроль четности, дуплекс задаются пользователем.

Реализация. Для реализации данного задания использовался язык C для упрощения демонстрации работы. Реализован процесс односторонней передачи сообщения с одного МК на другой с использованием терминала. Текст вводится в окне одного терминала (но не отображается там) и отображается в окне другого терминала.

Рис. 1. Схема в Proteus

Листинг на C.

Main.c

#include "Includes.h"

// Config word
__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_ON & CP_OFF & CPD_OFF);

// Define CPU Frequency
// This must be defined, if __delay_ms() or 
// __delay_us() functions are used in the code
//#define _XTAL_FREQ   4000000    

// Main function
void main()
{	
	unsigned char ch = 0;

	ANSEL  = 0x00;       // Set ports as digital I/O, not analog input
	ADCON0 = 0x00;		 // Shut off the A/D Converter
	CMCON  = 0x07;		 // Shut off the Comparator
	VRCON  = 0x00;	     // Shut off the Voltage Reference
	TRISIO = 0x08;       // GP3 input, rest all output
	GPIO   = 0x00;       // Make all pins 0
	
	InitSoftUART();		 // Intialize Soft UART

	while(1)
	{
		ch = UART_Receive();	// Receive a character from UART
		UART_Transmit(ch);		// Echo back that character
	}
}

Software_UART.c

#include "Includes.h"

void InitSoftUART(void)		// Initialize UART pins to proper values
{
	UART_TX = 1;			// TX pin is high in idle state
	
	UART_RX_DIR = 1;		// Input
	UART_TX_DIR = 0;		// Output
}

unsigned char UART_Receive(void)
{
	// Pin Configurations
    // GP1 is UART RX Pin

	unsigned char DataValue = 0;

	//wait for start bit
	while(UART_RX==1);

	__delay_us(OneBitDelay);
	__delay_us(OneBitDelay/2);   // Take sample value in the mid of bit duration

	for ( unsigned char i = 0; i < DataBitCount; i++ )
	{
		if ( UART_RX == 1 )   //if received bit is high
		{
			DataValue += (1<<i);
		}

		__delay_us(OneBitDelay);
	}

	// Check for stop bit
	if ( UART_RX == 1 )       //Stop bit should be high
	{
		__delay_us(OneBitDelay/2);
		return DataValue;
	}
	else                      //some error occurred !
	{
		__delay_us(OneBitDelay/2);
		return 0x000;
	}
}

void UART_Transmit(const char DataValue)
{
	/* Basic Logic
	   
	   TX pin is usually high. A high to low bit is the starting bit and 
	   a low to high bit is the ending bit. No parity bit. No flow control.
	   BitCount is the number of bits to transmit. Data is transmitted LSB first.

	*/

	// Send Start Bit
	UART_TX = 0;
	__delay_us(OneBitDelay);

	for ( unsigned char i = 0; i < DataBitCount; i++ )
	{
		//Set Data pin according to the DataValue
		if( ((DataValue>>i)&0x1) == 0x1 )   //if Bit is high
		{
			UART_TX = 1;
		}
		else      //if Bit is low
		{
			UART_TX = 0;
		}

	    __delay_us(OneBitDelay);
	}

	//Send Stop Bit
	UART_TX = 1;
	__delay_us(OneBitDelay);
}

Больше информации по работе с МК PIC можно найти здесь[2].

Пример 2

Исходные данные. Осуществить отображение показаний реостата в терминале в шестнадцатеричном виде в диапазоне 0x00-0xFF. Скорость передачи данных, контроль четности, дуплекс задаются пользователем.

Реализация. При выставлении значения на реостате данные непрерывно передаются в окно терминала с заданной скоростью, где нулю соответствует значение 0x90.

Рис. 2. Схема в Proteus

Листинг на Ассемблере.

processor 12f675

CC equ 0x22
COUNT equ 0x21
DELAY equ 0x20
T_C equ 0x23
INFO equ 0x24


SENT equ 0
FIRST equ 2
BITTOSEND equ 1


__CONFIG  _MCLRE_OFF & _INTRC_OSC_NOCLKOUT
include <p12f675.inc>

ORG 0
goto PRG

ORG 0004h
goto INT

ORG 0020h
PRG:
	bsf GPIO,1
	bcf T1CON,TMR1CS
	bsf CC,SENT
	bsf CC,FIRST
	bcf CC,BITTOSEND
	movlw 0
	movwf DELAY
	movlw 0
	movwf COUNT
	bsf STATUS,RP0		;bank 1
	movlw 0x11
	movwf ANSEL
	movlw 0x29
	movwf TRISIO
	bsf PIE1,TMR1IE
	bcf STATUS,RP0		;bank 0
	bsf INTCON,PEIE
	bsf INTCON,GIE
	movlw 0xff
	movwf TMR1H
	movlw 0x97
	movwf TMR1L
	movlw 0x81
	movwf ADCON0
	clrf GPIO
	movlw 0
	movwf CMCON
LOOP:
	CLRWDT
	btfss CC,SENT
	goto LOOP	
	btfsc ADCON0,GO
	goto $-1
	call WAIT
	bsf ADCON0,GO
	btfss CC,FIRST
	goto $--3
	bcf CC,FIRST
	goto LOOP
	call SEND
	goto LOOP

INT:
	btfsc PIR1,TMR1IF
	goto TIMER_INT
INT_RET:
	RETFIE

TIMER_INT:
	bcf PIR1,TMR1IF
	decfsz COUNT
	goto $--4
	bcf T1CON,TMR1ON
	bsf CC,SENT
	goto INT_RET
	btfss INFO,0
	bcf GPIO,1
	btfsc INFO,0
	bsf GPIO,1
	movlw 0x97
	movwf TMR1L
	movlw 0xff
	movwf TMR1H
	rrf INFO
	movlw 0x80
	iorwf INFO
	goto INT_RET

NOT_ZERO:
	
	RETURN

SEND:
	bsf STATUS,RP0		;bank 1
	movf ADRESL,0
	bcf STATUS,RP0		;bank 0
	movwf INFO
	bcf CC,SENT
	movlw 0x0B
	movwf COUNT
	bcf GPIO,1
	movlw 0x97
	movwf TMR1L
	movlw 0xff
	movwf TMR1H
	bsf T1CON,TMR1ON
	RETURN

WAIT:
	decfsz DELAY
	goto WAIT
	RETURN

END

Работа с отладочной платой AX-12

Цель работы. Реализовать работу алгоритмов из 7 и 8 лабораторных работ на отладочной плате AX-12.

Отладочная плата AX-12.

Рис. 3. Схема отладочной платы AX-12

С одной стороны, проблем с моделированием работы на отладочной плате быть не должно - нужно отключить WatchDog Timer и загрузить свою прошивку с расширением .hex на плату. С другой стороны, на AX-12 присутствуют ограничения, связанные непосредственно с реализацией самой платы: плата располагает 1 семисегментным индикатором, 8 диодами (причем одновременно они работать не могут), 3 кнопками-переключателями, 1 сдвиговым регистром, поэтому в некоторых случаях алгоритм придется пересмотреть.

Пример

Реализацию UART с использованием отладочной платы AX-12 представим следующим образом. На плате режим передачи или приема символов определяется переключателем GP5, если переключатель находится в положении RxD, плата будет в режиме приема данных по интерфейсу RS232, при перестановке переключателя в положение S3, кнопка S3 становится рабочей. Осуществлять передачу данных будет при помощи этой кнопки.

Алгоритм работы следующий. Если переключатель GP5 находится в положении RxD, с внешнего устройства осуществляется передача данных на плату, и принимаемые данные фиксируются на диодах (в шестнадцатиричном представлении). Если переключатель GP5 находится в положении S3, при нажатии на соответствующую кнопку будет осуществляться передача данных с платы на внешнее устройство (с платы будет передаваться некоторое фиксированное значение, указанное в коде программы - в данном примере, это символ "p").

Проиллюстрируем работу схемы. На рис.4 представлена схема в Proteus. Пусть схема находится в режиме приема символов, и с внешнего устройства был послан символ "1". Шестнадцатиричный код данного символа - 31, или в двоичном коде - 110001. Данное значение и высвечивается на диодах (старший разряд - диод D7, младший - D2). Работа схемы в этом режиме представлена на рис.5. Теперь пусть схема находится в режиме передачи символов и передается символ "p". Соответствущее значение высветится на терминале (рис.6).

Рис. 4. Схема в Proteus
Рис. 5. Схема в Proteus
Рис. 6. Схема в Proteus

Реализация на C:

#include <12F675.h>
#fuses NOWDT
#fuses NOMCLR
#fuses INTRC_IO
#fuses NOPROTECT
#fuses NOPUT
#fuses BROWNOUT

#use delay (clock = 4000000)

#define recieved PIN_A5
#define transmited PIN_A1
#define seven_seg PIN_A1
#define pin_clk PIN_A4
#define button PIN_A3
#define latch PIN_A2

byte data_out = 0x70;
byte data_in = 0;
byte press_detection = 0;
byte correct=0b11110000;
void clk()
{
   output_toggle(pin_clk);
   output_toggle(pin_clk);
}
void clk1()
{
   output_toggle(latch);
   output_toggle(latch);
}

void seg_out(byte data)
{
   byte i = 0;
   for (i = 1; i < 9; i++)
   {
      if (data & (1 << i))
         output_high(seven_seg);
      else
         output_low(seven_seg);
      clk();
   }
 
}

void uart_out()
{
  press_detection = 0;
   output_low(transmited);
   delay_us(308);
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   if (data_out & 1)
      output_high(transmited);
   else
      output_low(transmited);
   delay_us(208);
   data_out >>= 1;
   output_high(transmited);
   delay_us(308);
   data_out = 0x70;
void uart_in()
{
   //-------------------
   byte i = 0;
   
    
    data_in <<= 1;
    delay_us(312); 
data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
      data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
      data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
       data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
      data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
      data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
      data_in |= (input(recieved));
      data_in <<= 1;
      delay_us(208);
      
            
      delay_us(208);
      data_in |= 1;
       
      seg_out(data_in);
      clk1();
      
}

void uart_clear()
{
   delay_us(312);
   byte i = 0;
   data_in = 0;
    
      data_in |= 0b00000001;
   
    
  seg_out(data_in);
   
}

void main ()
{
   output_high(transmited);
   output_low(pin_clk);
   output_low(seven_seg);
   output_high(latch);

   while (1)
   {
      press_detection |= input(button);
      
      if ((!input(button)) && (press_detection == 1))
      {
         delay_ms(22);
         if ((!input(button))&& (press_detection == 1))
            uart_out();
      }
      if (!input(recieved))  
      {
         data_in = 0;
         data_in |= (input(recieved));
        uart_in();
         delay_ms(20);
      }
   }

}

Примечания