Ccs c for pic16F877a mục lục I. Tổng quan về ccs vì sao ta sử dung ccs ?



tải về 1.15 Mb.
trang12/15
Chuyển đổi dữ liệu23.08.2016
Kích1.15 Mb.
#26977
1   ...   7   8   9   10   11   12   13   14   15

10.4. Sử dụng capture_LCD

#include <16F877A.h>

#include

#use delay(clock=20000000)

#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#bit TMR1IF = 0x0C.0
#include
int16 CCP1Value; // Gia tri CCP hien tai

int16 CCP1OldValue; // Gia tri CCP truoc do

BOOLEAN CCP1Captured;

float Freq;

int8 char1,char2,char3,char4,char5,char6;
#int_CCP1

CCP1_isr()

{

if(TMR1IF)



{

CCP1Value = CCP_1 +(65535-CCP1OldValue);

CCP1OldValue = CCP_1;

TMR1IF=0;

}

else


{

CCP1Value = CCP_1 - CCP1OldValue;

CCP1OldValue = CCP_1;

}

CCP1Captured = TRUE;



}

//--------------------------------------------------------------------------

#INT_TIMER1

Timer1_isr()

{

IF (RB0==1) RB0=0;



Else RB0=1;

}

//----------------------------------------



void Init_ccp(void)

{

setup_ccp1(CCP_CAPTURE_RE);



setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

CCP1Value = 0;

CCP1OldValue = 0;

CCP1Captured = TRUE;

enable_interrupts(INT_CCP1);

//enable_interrupts(INT_TIMER1);

enable_interrupts(GLOBAL);

}

//--------------------------------------------------------------------------



void Convert_CCP1()

{

long temp;



int8 temp2;

Freq = 1.0/((float)CCP1Value*1.6e-6);

temp = (long)freq;

char1 = ((temp / 100) + 0x30);

temp2 = (temp % 100);

char2 = ((temp2 / 10) + 0x30);

char3 = ((temp2 % 10) + 0x30);

}

//---------------------------------------------------------------



void main()

{

TRISB = 0;



Init_ccp();

LCD_init();

printf("Frequence test:\r\n");

while (TRUE) {

if (CCP1Captured) {

// F = 1/T

// Timer1 prescaler DIV_BY_8

// Pic16F877A 4MHz -> 0.000001 * 8 = 1uS * 8

// PIC16f877a 20MHz -> 0.0000002 * 8

Convert_CCP1();

LCD_putcmd(0x80);

Printf(LCD_putchar,"Freq = ");

LCD_putchar(char1);

LCD_putchar(char2);

LCD_putchar(char3);

Printf(LCD_putchar," Hz");


printf("Freq:%f\r\n",Freq);

CCP1Captured = FALSE;

}

}

}



10.5. Sử dụng capture

#include <16F877A.h>

#use delay(clock=4000000)

#fuses HS,NOWDT, NOPROTECT

//#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9,errors)


int16 CCP1Value;

int16 CCP1OldValue;

BOOLEAN CCP1Captured;
#int_CCP1 // Ngat do CCCP1 xay ra, thuc hien lenh...

CCP1_isr()

{

CCP1Value = CCP_1 - CCP1OldValue;



CCP1OldValue = CCP_1;

CCP1Captured = TRUE;

}

//--------------------------------------------------------------------------



void Init_ccp(void) //Khoi tao chuc nang CCCP

{

setup_ccp1(CCP_CAPTURE_RE);



setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

CCP1Value = 0;

CCP1OldValue = 0;

CCP1Captured = TRUE;

enable_interrupts(INT_CCP1);

enable_interrupts(GLOBAL);

}

//--------------------------------------------------------------------------



void main()

{

float Freq;



Init_ccp();

printf("Frequence test:\r\n");

while (TRUE) {

if (CCP1Captured) {

// F = 1/T

// Timer1 prescaler DIV_BY_8

// Pic16F876 4Mz -> 0.000001 * 8

Freq = 1.0/((float)CCP1Value*8e-6);

printf("Freq:%f\r\n",Freq);

CCP1Captured = FALSE;

}

}

}



11. SPI

// SPI MICROWIRE INTERFACE HANDLER

// COPYRIGHT PROPERTY OF ALPHADATA DESIGNS LIMITED (c) 1999

// published by permission of Alphadata designs on

// Hi-Tech C website, http://www.workingtex.com/htpic. Thanks!

// P4/0 : OUTPUT : DATA OUT

// P4/1 : OUTPUT : CLOCK

// P4/2 : OUTPUT : CHIP SELECT ATOD

// P4/3 : OUTPUT : CHIP SELECT DTOA

// P4/7 : INPUT : DATA IN

//

//------------------------------------------------------



// Version History

//------------------------------------------------------

// Issue 1.0 : 21/12/1999 : First Officially Released

//------------------------------------------------------


#include "h8genlib.h"

#include "ioh8314.h"


extern byte p4dr;
// Select device

void spi_dac_select(void)

{

p4dr = p4dr & 0b11110111;



P4DR = p4dr;

}

// Deselect device



void spi_dac_deselect(void)

{

p4dr = p4dr | 0b00001000;



P4DR = p4dr;

}

// Select device



void spi_adc_select(void)

{

p4dr = p4dr & 0b11111011;



P4DR = p4dr;

}

// Deselect device



void spi_adc_deselect(void)

{

p4dr = p4dr | 0b00000100;



P4DR = p4dr;

}

// Set clock high



void spi_hiclock(void)

{

p4dr = p4dr | 0b00000010;



P4DR = p4dr;

}

// Set clock low



void spi_loclock(void)

{

p4dr = p4dr & 0b11111101;



P4DR = p4dr;

}

// Set Data high



void spi_hidata(void)

{

p4dr = p4dr | 0b00000001;



P4DR = p4dr;

}

// Set data low



void spi_lodata(void)

{

p4dr = p4dr & 0b11111110;



P4DR = p4dr;

}

// end



12. Các chuẩn giao tiếp

12.1. Chuẩn giao tiếp I2C

-Sơ đồ:



-Mình dùng lệnh I2C trong CCS có hiệu quả ko ?!

Vì mình đang viết thử I2C. Thấy chương trình mẫu(EX_Slave) trong CCS C mô phỏng bộ nhớ ngoài 24xx chuẩn, nên nạp chạy thử thấy: viết từ Master (Ctr Mater lấy ví dụ: EX_EXTEE) ít nhất là 4 lần mới được, còn đọc thì lại ko được. Xem tài liệu thì thấy có rất nhiều bit bẫy tình huống I2C, nhưng các lệnh về I2C trong CCS thì đơn giản và ít. Vậy, có vấn đề gì không.

Code:

#include <16F876A.h>



#fuses XT,NOWDT,NOPROTECT,NOLVP

#use delay(clock=4000000)

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)
typedef enum {NOTHING, CONTROL_READ,

ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;

I2C_STATE fState;

BYTE address, buffer[0x10];


#INT_SSP

void ssp_interupt ()

{

BYTE incoming;



if (i2c_poll() == FALSE) {

if (fState == ADDRESS_READ) { //i2c_poll() returns false on the

i2c_write (buffer[address]);//interupt receiving the second

fState = NOTHING; //command byte for random read operation

}

}

else {



incoming = i2c_read();

if (fState == NOTHING){

fState = CONTROL_READ;

}

else if (fState == CONTROL_READ) {



address = incoming;

fState = ADDRESS_READ;

}

else if (fState == ADDRESS_READ) {



buffer[address] = incoming;

fState = NOTHING;

}

}

}



void main ()

{

int i;


fState = NOTHING;

address = 0x00;

for (i=0;i<0x10;i++)

buffer[i] = 0x00;

enable_interrupts(GLOBAL);

enable_interrupts(INT_SSP);


while (TRUE) {}

}
Hà vừa thử chtr I2c: Master 16F877A, Slave 16F876A, cùng giao tiếp PC để kiểm tra dữ liệu đọc và viết của Master và Slave> Thấy rất tốt ! I2C hay thiệt! Nhiêm vụ bây giờ mình chỉ tạo giao thức dữ liệu, còn chtr service plug&play slave thì thấy hơi khó! Nhưng mònh cố gắn viết thử. Cảm ơn Hoanf, mọi người rất nhiều !!

Code:

**********************************************



Chtr Master, mình thay đổi chút ít từ chtr mẫu EX_EXTEE.

1.chỉ liên kết 2401.c (thay vì địa chỉ mặc đinh là 0xa0,

mình thay là 0x10).

2. Vẫn truyền lệnh từ PC

**********************************************

#include <16F877A.h>

#fuses XT,NOWDT,NOPROTECT,NOLVP

#use delay(clock=4000000)

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include

#include <2401.c>


void main() {
BYTE value, cmd;

EEPROM_ADDRESS address;


init_ext_eeprom();
do {

do {


printf("\r\nRead or Write: ");

cmd=getc();

cmd=toupper(cmd);

putc(cmd);

} while ( (cmd!='R') && (cmd!='W') );
printf("\n\rLocation: ");
address = gethex1();

if(cmd=='R')

printf("\r\nValue: %X\r\n",READ_EXT_EEPROM( address ) );

if(cmd=='W') {

printf("\r\nNew value: ");

value = gethex();

printf("\n\r");

WRITE_EXT_EEPROM( address, value );

}

} while (TRUE);



}

Code:

**********************************************

Chtr Slave, thì có thay đổi chút ít từ chtr mẫu EX_Slave:

1. giám sát 3 ô nhớ trên PC

2. khai báo địa chỉ la 0x10.

**********************************************

#include <16F876A.h>

#fuses XT,NOWDT,NOPROTECT,NOLVP

#use delay(clock=4000000)

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)


#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)
BYTE address, buffer[0x10];
#INT_SSP

void ssp_interupt ()

{

BYTE incoming, state;


state = i2c_isr_state();
if(state < 0x80) //Master is sending data

{

incoming = i2c_read();



if(state == 1) //First received byte is address

address = incoming;

if(state == 2) //Second received byte is data

buffer[address] = incoming;

}

if(state == 0x80) //Master is requesting data



{

i2c_write(buffer[address]);

}

}

void main ()



{

enable_interrupts(GLOBAL);

enable_interrupts(INT_SSP);
while (TRUE) {

printf("\r\nValue0: %X\r\n",buffer[0]);

delay_ms(1000);

printf("\r\nValue1: %X\r\n",buffer[1]);

delay_ms(1000);

printf("\r\nValue2: %X\r\n",buffer[2]);

delay_ms(1000);

printf("\r\nValue3: %X\r\n",buffer[3]);

delay_ms(1000);

}

}



Mình mới viết được chương trình giao tiếp I2C đơn giản dùng các hàm của CCS.

Mời các bạn xem và cho nhận xét

Master: truyền dữ liệu cho Slave. Mỗi lần truyền 1 byte.

Code:

#include <16F877A.H>

#fuses XT,NOWDT,NOPROTECT,NOLVP

#use Delay(Clock=4000000)


#define SLAVE_ADDRESS 0x10

#use i2c(master, sda=PIN_C4, scl=PIN_C3)


void write_I2C(int8 a)

{

i2c_start();



i2c_write(SLAVE_ADDRESS);

i2c_write(a);

i2c_stop();

}

void main()



{

int8 value;

value = 0;

while(1){

write_I2C(value);

value++;


delay_ms(100);

}

}



Slave thì chỉ tiến hành kiểm tra có phải Master truyền hay kô. Nếu truyền thì nhận byte dữ liệu và hiển thị lên port_B:

Code:

#include <16F877A.H>

#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(Clock=4000000)

#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)


int8 value;

#INT_SSP


void i2c_isr()

{

int8 state;



int8 address;

state = i2c_isr_state();

if(state == 0)

address = i2c_read();

else if(state < 0x80)

value = i2c_read();

}

void main()



{

enable_interrupts(GLOBAL);

enable_interrupts(INT_SSP);
set_tris_b(0x00);

while(1){

output_b(value);

}

}



Mình gặp trục trặc khi đọc dữ liệu từ Slave về.
Đây là đoạn code sử dụng cho 2 con PIC 18F877A.
Master: Yêu cầu Slave nhận dữ liệu liên tục (cách nhau 500ms) và nó sẽ hiển thị giá trị nhận được lên Port_b. Dùng leds để quan sát.

Code:

#include <16F877A.H>

#fuses XT,NOWDT,NOPROTECT,NOLVP

#use Delay(Clock=4000000)


#define SLAVE_ADDRESS 0x10

#use i2c(master, sda=PIN_C4, scl=PIN_C3)


int8 read_I2C()

{

int8 value;


i2c_start();

i2c_write(SLAVE_ADDRESS + 1);

value = i2c_read();

i2c_stop();

return value;

}

void main()



{

int8 value;


set_tris_b(0x00);

while(1){

value = read_I2C();

output_b(value);

delay_ms(500);

}

}



Slave: Truyền dữ liệu cho master và mỗi lần truyền thì giá trị cần truyền tăng lên 1 đơn vị.

Code:

#include <16F877A.H>

#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(Clock=4000000)

#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)


int8 value = 0x01;
#INT_SSP

void i2c_isr()

{

int8 state;



int8 address;

state = i2c_isr_state();

if(state >= 0x80){

i2c_write(value);

value++;

}

}



void main()

{

enable_interrupts(GLOBAL);



enable_interrupts(INT_SSP);
set_tris_b(0x00);

while(1){

output_b(value);

}

}



Theo Hà nghĩ, ở Master, khi mình đọc cũng phải chờ xung ACK từ Slave thì chtr ko bị rối.
Bạn thử thêm một chtr con chờ Bus trong <2401.c>:

Code:

//**************code thêm vào*********************

BOOLEAN ext_eeprom_ready()

{

int1 ack;



i2c_start();

ack = i2c_write(SLAVE_ADDRESS);

i2c_stop();

return !ack;

}

//**********************************************



int8 read_I2C()

{

int8 value;



while(!ext_eeprom_ready()); // code thêm vào

i2c_start();

i2c_write(SLAVE_ADDRESS + 1);

value = i2c_read();

i2c_stop();

return (value);

}

void main()



{

int8 value;


value = 0x00;

set_tris_b(0x00);


while(1){

value = read_I2C();

output_b(value);

delay_ms(500);

}

}

12.1.1. Master_Slave





12.1.1.1. I2Cmaster

//**************************************************************************

// Day la chuong trinh vi du su dung truyen thong I2C

// This program is a sample of I2C comunication.

//This is master mode

//This include next funtions:

// 1. Send ASCII code periodically to slave

// 2. Display send data on LCD display

// Hanoi: 12/5/2007

//Writer: Nguyen Khac Hieu

//user: all of my friends and students etc...

//**************************************************************************

#include <16F84A.h>

#fuses NOWDT,PUT,HS,NOPROTECT

#use delay(clock=4000000)

#byte PORTA=5

#byte PORTB=6

// Khai bao LCD

#define rs PIN_A2

#define rw PIN_A1

#define stb PIN_A0

#byte db = 6 // khai bao c?ng D cho LCD

#define Amode 0x0

#define Bmode 0x0F

#include

#use I2C(master, sda=PIN_A4, scl=PIN_A3)

// Chuong trinh chinh

void khoitao();

void main(void)

{

int asci,i;



set_tris_b(Bmode);

set_tris_a(Amode);

lcd_init();

lcd_clear();

lcd_data("Start I2C test");

delay_ms(3000);

while(1)

{

asci=0x30;



lcd_clear();

do{


i2c_start();

i2c_write(0xa0);

for(i=1;i<=8;++i){

i2c_write(asci);

lcd_data(asci);

asci=asci+1;

delay_us(100);

}

i2c_stop();



delay_ms(1000);
}while(asci<0xFE);

}

}



12.1.1.2. I2Cslave

//**************************************************************************

// This program is a sample of I2C comunication.

//This is slave mode

//This include next funtions:

// 1. Receive data from I2C master CPU

// 2. Display received data on LCD display

// Hanoi: 12/5/2007

//Writer: Nguyen Khac Hieu

//user: all of my friends, my students etc...

//**************************************************************************

#include <16F877A.h>

#fuses NOWDT,PUT,HS,NOPROTECT

#use delay(clock=4000000)

// Khai bao LCD

#define rs PIN_A2

#define rw PIN_A1

#define stb PIN_A0

#byte db = 0x08

#define Amode 0x00

#define Dmode 0x0F

#include

#use I2C(slave, sda=PIN_C4, scl=PIN_C3, address=0xa0, NOFORCE_SW)

// Chuong trinh chinh

void khoitao();

void main(void)

{

int indata;



set_tris_d(Dmode);

set_tris_a(Amode);

// set_tris_c(0x99);

lcd_init();

lcd_clear();

lcd_data("Start I2C test");

delay_ms(2000);

lcd_clear();

while(1)

{

if(i2c_poll()){



indata=i2c_read();

lcd_data(indata);

}

}

}



12.1.2. lcd1_lib

///////////////////////////////////////////////

// LCD control Library

// functions are below

// lcd_init()-------- initialize

// lcd_ready()------- busy check

// lcd_cmd(cmd)------ send command

// lcd_data(string)-- display string

// lcd_clear() ------ clear display

//////////////////////////////////////////////

/////////// lcd ready check function

int lcd_ready(){

int high,low;

set_tris_b(Bmode | 0xF0); //upper is input

output_low(rs);

output_high(rw); //read mode

output_high(stb);

high= PORTB& 0xF0; //input upper

output_low(stb);

output_high(stb);

low=PORTB & 0xF0; //input lower

output_low(stb);

set_tris_b(Bmode);

return(high | (low>>4)); //end check

}

////////// lcd display data function



void lcd_data(int asci){

PORTB = asci; //set upper data

output_low(rw); //set write

output_high(rs); //set rs high

output_high(stb); //strobe

output_low(stb);

asci=asci<<4;

PORTB = asci; //set lower data

output_high(stb); //strobe

output_low(stb);

while(bit_test(lcd_ready(),7));

}

////////// lcd command out function



void cmdout(int cmd){

PORTB = cmd; //set upper data

output_low(rw); //set write

output_low(rs); //set rs low

output_high(stb); //strobe

output_low(stb);

cmd=cmd<<4;

PORTB = cmd; //set lower data

output_high(stb); //strobe

output_low(stb);

}

void lcd_cmd(int cmd){



cmdout(cmd);

while(bit_test(lcd_ready(),7)); //end check

}

////////// lcd display clear function



void lcd_clear(){

lcd_cmd(1); //initialize command

}

///////// lcd initialize function



void lcd_incmd(int cmd){

PORTB = cmd; //mode command

output_low(rw); //set write

output_low(rs); //set rs low

output_high(stb); //strobe

output_low(stb);

delay_us(100);

}

void lcd_init(){



delay_ms(15);

lcd_incmd(0x30); //8bit mode set

delay_ms(5);

lcd_incmd(0x30); //8bit mode set

delay_ms(1);

lcd_incmd(0x30); //8bit mode set

lcd_incmd(0x20); //4bit mode set

lcd_cmd(0x2E); //DL=0 4bit mode

lcd_cmd(0x08); //disolay off C=D=B=0

lcd_cmd(0x0D); //display on C=D=1 B=0

lcd_cmd(0x06); //entry I/D=1 S=0

}

12.1.3. lcd2_lib

///////////////////////////////////////////////

// LCD control Library

// functions are below

// lcd_init()-------- initialize

// lcd_ready()------- busy check

// lcd_cmd(cmd)------ send command

// lcd_data(string)-- display string

// lcd_clear() ------ clear display

//////////////////////////////////////////////

/////////// lcd ready check function

int lcd_ready(){

int high,low;

set_tris_d(Dmode | 0xF0); //upper is input ------------

output_low(rs);

output_high(rw); //read mode

output_high(stb);

high=db & 0xF0; //input upper

output_low(stb);

output_high(stb);

low=db & 0xF0; //input lower

output_low(stb);

set_tris_d(Dmode);//---------------------------------------

return(high | (low>>4)); //end check

}

////////// lcd display data function



void lcd_data(int asci){

db = asci; //set upper data

output_low(rw); //set write

output_high(rs); //set rs high

output_high(stb); //strobe

output_low(stb);

asci=asci<<4;

db = asci; //set lower data

output_high(stb); //strobe

output_low(stb);

while(bit_test(lcd_ready(),7));

}

////////// lcd command out function



void cmdout(int cmd){

db = cmd; //set upper data

output_low(rw); //set write

output_low(rs); //set rs low

output_high(stb); //strobe

output_low(stb);

cmd=cmd<<4;

db = cmd; //set lower data

output_high(stb); //strobe

output_low(stb);

}

void lcd_cmd(int cmd){



cmdout(cmd);

while(bit_test(lcd_ready(),7)); //end check

}

////////// lcd display clear function



void lcd_clear(){

lcd_cmd(1); //initialize command

}

///////// lcd initialize function



void lcd_incmd(int cmd){

db = cmd; //mode command

output_low(rw); //set write

output_low(rs); //set rs low

output_high(stb); //strobe

output_low(stb);

delay_us(100);

}

void lcd_init(){



delay_ms(15);

lcd_incmd(0x30); //8bit mode set

delay_ms(5);

lcd_incmd(0x30); //8bit mode set

delay_ms(1);

lcd_incmd(0x30); //8bit mode set

lcd_incmd(0x20); //4bit mode set

lcd_cmd(0x2E); //DL=0 4bit mode

lcd_cmd(0x08); //disolay off C=D=B=0

lcd_cmd(0x0D); //display on C=D=1 B=0

lcd_cmd(0x06); //entry I/D=1 S=0

}

12.2. Giao tiếp RS232



Serial Port - lập trình giao tiếp nối tiếp

Tôi xin copy tất cả các bài của tôi vào box này để cho tổng quát hơn giới thiệu về giao tiếp nối tiếp qua Serial Port như RS-232, RS-485. Hi vọng là cho các bạn có kiến thức đầy đủ về lập trình nối tiếp nói chung và qua RS232, RS-485 nói riêng.



Giới thiệu giao tiếp cổng com - chapter1

Tôi xin giới thiệu cho các bạn chi tiết các thông tin, cách lập trình truyền thông nối tiếp dùng chuẩn RS-232 và RS-485.
Có thể có nhiều bạn đã biết rồi hoặc là chưa biết nhưng tôi mong rằng sẽ bổ sung cho các bạn một số điều cơ bản.
Tất cả mọi vấn đề tôi dịch từ cuốn Serial_complete của Jan Axelson và thực tế lập trình truyền thông giao tiếp với vdk AT89C51( một loại vi điều khiển đơn giản). Hi vọng các vấn đề tôi đưa ra sẽ làm các bạn môt phần nào hiểu biết thêm về cổng thông dụng này cổng Comm( communicactions).
Do thời gian không có nhiều vừa làm vừa ôn thi nên mỗi ngày tôi sẽ up lên từng vấn đề một. Mong các bạn góp ý thêm. Tôi làm cái này không có ý qua mặt các cao thủ, mong các cao thủ bỏ quá cho. Các bạn có thể có thêm nhiều ví dụ khi vào trang web http://www.lvr.com


tải về 1.15 Mb.

Chia sẻ với bạn bè của bạn:
1   ...   7   8   9   10   11   12   13   14   15




Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2024
được sử dụng cho việc quản lý

    Quê hương