View Full Version : CCS C for PIC16F877A
cuopbienquin
11-07-2007, 02:34 PM
thx bạn nhiều.Mình chạy được rồi,ah,mà bạn giải thích mình thay "Xt" trong dòng đó bằng "HS" la sao hả bạn.
anh_gioi
12-07-2007, 09:52 AM
bài này:
/*-----------------------------------------------------------------------------
* Author : nhh
* Date : 05/04/06
* Hardware : PIC16F877A
* Compiler : CCS C 3.249
* Description : Hien thi LCD
*================================================= ============================*/
#include <16F877A.h>
//#include <DEFS_16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define RS RD0
#define RW RD1
#define E RD2
#define LCD PORTB
/*Ham yeu cau goi lenh dieu khien LCD*/
void comnwrt(void)
{
RS = 0;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
/*Ham yeu cau goi du lieu hien thi len LCD*/
void datawrt(void)
{
RS = 1;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
/*Ham main*/
void main(void)
{
set_tris_B(0);
set_tris_D(0);
delay_ms(100); // Tao tre 100ms cho LCD khoi dong
LCD = 0x38; // Hai hang, ma tran dot 5*7, 8 bit interface
comnwrt();
LCD = 0x0C; // Bat hien thi, tat con tro
comnwrt();
LCD = 0x85; // Vi tri hang 1,cot 6
comnwrt();
LCD = 'B'; // Xuat dong chu "BE YEU" ra LCD
datawrt();
LCD = 'E';
datawrt();
LCD = ' ';
datawrt();
LCD = 'Y';
datawrt();
LCD = 'E';
datawrt();
LCD = 'U';
datawrt();
LCD = '!';
datawrt();
}
bài này không bít gọi file DEFS_16F877A.h ra như thế nào nhỉ?
mong mọi người chỉ dùm.thank!
namqn
12-07-2007, 06:56 PM
thx bạn nhiều. Mình chạy được rồi,ah,mà bạn giải thích mình thay "Xt" trong dòng đó bằng "HS" la sao hả bạn.
XT là đặt bộ dao động ở chế độ dùng với thạch anh tần số thấp (4 MHz trở lại), HS là đặt bộ dao động ở chế độ dùng với thạch anh tần số cao hơn (4 MHz đến maximum của chip).
Thân,
anh_gioi
12-07-2007, 07:30 PM
mọi ngừoi ơi! xem hộ mã này với
không bít có sai gì ko ,nó không báo lỗi nhưng nó không hiển thị chữ
#include "16F877A.h"
#include "C:\Documents and Settings\Administrator\Desktop\DEFS_16F877A\DEFS_1 6F877a.h"
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock = 4M)
#define RS RD0
#define RW RD1
#define E RD2
#define LCD portB
//tao ham goi lenh dieu khien
void comnwrite(){
RS = 0; //chon thanh ghi lenh
RW = 0; //chon che do ghi
E = 1; //tao suon xung
E = 0;
delay_ms(1); //tao do tre cho LCD
}
// tao ham ghi du lieu
void datawrite(){
RS = 1;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
//ham chinh
void main(){
set_tris_b(0);
set_tris_d(0);
delay_ms(100); //tao tre cho lcd khoi dong
LCD = 0x38; //tao ma tran 5x7
comnwrite();
LCD = 0x0C ; //bat hien thi,tat con tro
comnwrite();
LCD = 0x80; //dau dong thu nhat
comnwrite();
//xuat chu ANH_GIOI
LCD = 'A';
datawrite();
LCD = 'N';
datawrite();
LCD = 'H';
datawrite();
LCD = '_';
datawrite();
LCD = 'G';
datawrite();
LCD = 'I';
datawrite();
LCD = 'O';
datawrite();
LCD = 'I';
datawrite();
}
thank!
namqn: bạn xem lại tôi sửa như thế nào để hiển thị code, sau đó bạn làm như vậy khi post code. Tôi không thể sửa cho mọi post có code được.
anh_gioi
12-07-2007, 08:43 PM
kiểm tra lại hóa ra chẳng có lỗi gì cả.
tranvanthuong
13-07-2007, 11:33 AM
trời đất làm tui hoa cả mắt!!!
tranvanthuong
13-07-2007, 11:35 AM
kiểm tra lại hóa ra chẳng có lỗi gì cả.
tui bảo đảm với bạn với chương trình này khi lắp mạch thật thì sẽ chắc chắn mạch không chạy được bạn xem lại nhé!
anh_gioi
13-07-2007, 03:07 PM
cậu nói đúng rồi!
mình lắp mạch thật mà chẳng thấy gì cả?
cậu có thể nói cho mình sai ở chỗ nào ko?
cám ơn trước nha!
anh_gioi
13-07-2007, 03:12 PM
đây là đoạn mã mình cho chạy thật nhưng chẳng thấy báo gì cả:
#include "16F877A.h"
#include "C:\Documents and Settings\Administrator\Desktop\DEFS_16F877A\defs_1 6f877a.h"
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock = 8M)
#define RS RD0
#define RW RD1
#define E RD2
#define LCD portb
const unsigned char digital[]="TA LA VO DICH HA HA...!";
INT I=0;
//TAO HAM LENH
void commwrite(){
RS = 0;
RW = 0;
E = 1;
E = 0;
delay_ms(100);}
//tao ham gui du lieu
void datawrite(){
RS = 1;
RW = 0;
E = 1;
E = 0;
// delay_ms(10);
}
//ham chinh
void main(){
set_tris_b(0);
set_tris_d(0);
delay_ms(100);
LCD = 0x38; //tao ma tran 5x7
commwrite();
LCD = 0x0c; //tat con tro,bat hien thi
commwrite();
LCD = 0x80; //con tro ve dong dau tien
while(1){
LCD = digital[i];
datawrite();
delay_ms(100);
i++;
if(i ==13){ LCD = 0xc2;
commwrite();
delay_ms(100);}
if(i == 24){ LCD = 0x01;
commwrite();
delay_ms(500);
LCD = 0x80;
commwrite();
i = 0;}
}
}
mong mọi người xem dùm cái !
namqn: nhắc bạn một lần nữa về việc dùng các thẻ code để định dạng. Hãy xem tôi sửa post của bạn ra sao để biết cách làm.
anh_gioi
13-07-2007, 10:44 PM
anh da sủa cho em đâu ạ?
namqn
13-07-2007, 11:22 PM
anh da sủa cho em đâu ạ?
Tôi sửa trong post của bạn. Khi bạn đã đăng nhập thì có thể nhấn nút edit của post đó để sửa, khi đó sẽ thấy tôi sửa nó như thế nào.
Thân,
anh_gioi
14-07-2007, 10:15 AM
edit là chỉnh sửa bài của mình mà?
anh là ơn có thể xem code củ em ở cuối ạ.
hic...em mơi mua lcd mà chảng hiêrn thị được.tức quá....muốn cho cái búa..
namqn
14-07-2007, 07:19 PM
edit là chỉnh sửa bài của mình mà?
anh là ơn có thể xem code củ em ở cuối ạ.
hic...em mơi mua lcd mà chảng hiêrn thị được.tức quá....muốn cho cái búa..
Có khả năng bạn cần khởi tạo module LCD trước khi đặt chế độ hiển thị (tôi đã viết 1 lần rồi, nhưng bây giờ tìm bằng chức năng search của diễn đàn thì không ra). Tôi nói lại vậy (quy trình cho các module dùng chip điều khiển tương thích HD44780):
- Làm trễ một khoảng thời gian khi mới bật nguồn cho LCD (40 ms từ thời điểm Vdd = 2.7V, hay 15 ms từ thời điểm Vdd = 4.5V)
- Xuất lệnh 0x33 (0x30 đến 0x3F đều ok)
- Chờ khoảng 4.1 ms trở lên
- Xuất lệnh 0x33 (0x30 đến 0x3F đều ok)
- Chờ khoảng 100 us trở lên
- Xuất lệnh 0x33 (0x30 đến 0x3F đều ok)
- Xuất lệnh đặt chế độ (của bạn là 0x38)
- Xuất lệnh tắt màn hình 0x08
- Xuất lệnh xóa màn hình 0x01
- Xuất lệnh đặt chế độ nhập dữ liệu (tăng hay giảm địa chỉ, có dịch màn hình hay không)
Đó là quy trình khởi tạo cho module LCD chưa từng làm việc lần nào với vi điều khiển của bạn. Thông thường, khi module đã được khởi tạo rồi thì những lần sau bạn có thể dùng thẳng các lệnh đặt chế độ mà không cần thực hiện quy trình khởi tạo như trên.
Thân,
anh_gioi
16-07-2007, 07:45 PM
cám ơn anh ạ.em đã cho hiển thị được lên LCD rùi ạ.nhưng chỉ hiển thị chữ không dấu thui,bây giờ em muốn hiển thị chữ có dấu thì làm thế nào ạ?
em cám ơn!!!!
bien_van_khat
16-07-2007, 08:11 PM
Để làm chữ có dấu tối thiểu bạn phải có bộ font chữ có dấu, nhưng với LCD kiểu ký tự dạng như 16x2, 16x4 thì hiển thị chữ có dấu rất xấu.
Làm cái này trên LCD graphic tốt hơn nhiều.
anh_gioi
16-07-2007, 09:15 PM
vậy bộ font này là loại bộ font nào? hiển thị xấu cũng được,chủ yếu mình muốn xem các làm như thế nào thui
(mình sử dụng 16F877A,LCD 16x2)
bien_van_khat
16-07-2007, 10:56 PM
Mình ko theo dõi luồng này, nên ko chắc vấn đề này đã được đề cập hay chưa, bạn nên tìm lại trong diễn đàn, ở đây mình chỉ nói sơ qua.
Mỗi ký tự hiển thị trên lcd thường có kích thước 7 hàng x 5 cột do đó được xác định bởi 7byte, 3 bit cao nhất mỗi byte ko sử dụng. VD:
0x0E
0x0E
0x04
0x04
0x04
0x04
0x0C
Tạo thành chữ J hoa
Để có bộ font của riêng mình công việc của bạn là tìm ra các byte này ứng với mỗi ký tự. Công đoạn này tốn rất nhiều công sức nếu làm bằng tay, thường người ta dùng phần mềm, nhưng các phần mềm này lại thường ko free.
namqn
16-07-2007, 11:08 PM
vậy bộ font này là loại bộ font nào? hiển thị xấu cũng được,chủ yếu mình muốn xem các làm như thế nào thui
(mình sử dụng 16F877A,LCD 16x2)
LCD chủ yếu hiển thị bằng CGROM (Character Generator Read Only Memory), tức là bạn chỉ cần cho biết mã ASCII của ký tự, các pattern thể hiện ký tự (5x7, 5x8 hay 5x10) sẽ được lấy từ ROM. Các bộ điều khiển tương thích HD44780 cũng cho phép người dùng tự định nghĩa tối đa 8 ký tự (5x7 hay 5x8) trong vùng CGRAM (Character Generator Random Access Memory). Vùng nhớ này gồm 64 byte, chứa trực tiếp các pattern để tạo ký tự, và người dùng được phép ghi vào. Tuy nhiên, chỉ có thể vẽ thêm 8 ký tự, nên việc bạn muốn hiển thị tiếng Việt trên LCD ký tự là việc rất khó khăn và hạn chế. Nếu bạn vẫn muốn làm thì hãy tìm đọc datasheet của HD44780 và các tutorial trên mạng. Cách làm khá dài dòng nên không tiện nêu trên diễn đàn.
Một link để tham khảo:
http://deanandara.com/robots/ApuLcd.html
Thân,
anh_gioi
17-07-2007, 12:02 AM
vậy nếu hiển thị trên LCD muốn dễ dàng thì em phải sử dụng lợi LCD khác a(ko phải loại 16x2)như loại mà bien_van_khat đã nói ạ.ngoài ra anh có thể nêu cho em những loại LCD lào nữa ko ạ(tất nhiên kinh phi mua LCD cũng phải rẻ ạ)
namqn
17-07-2007, 01:49 AM
LCD thông thường có 2 loại khác nhau về cách thức hiện thực: LCD ký tự và LCD đồ họa. LCD ký tự có các ô định nghĩa sẵn sẽ hiển thị các ký tự nằm trong bộ ROM ký tự hay vài ký tự do người dùng định nghĩa. LCD đồ họa cho phép bạn vẽ (hiển thị) bất kỳ điểm ảnh nào, nó cũng có chế độ hiển thị ký tự. Tất nhiên LCD đồ họa thì giao tiếp phức tạp hơn và cũng đắt tiền hơn. Bạn nên dùng LCD ký tự khi mới làm quen với LCD, sau đó có nhu cầu thì chuyển sang LCD đồ họa. LCD đồ họa gần gũi nhất là các màn hình tại các quầy counter tính tiền của siêu thị, các màn hình trong các máy trò chơi bỏ túi, ...
Thân,
sandro_bk
18-07-2007, 02:34 PM
chào các bạn mình mới học pic nên chưa biết nhiều mong được sự giúp đỡ,
tui có vài câu hỏi mong được chỉ giáo
tui sử dụng ngắt timer nhưng thấy lệnh
set_timer0(); ko có tác dụng nghĩa là đặt số mấy cũng ko thấy thay đổi
thậm chí ko có lệnh đó vẫn chạy như thường
bạn nào làm ngắt timer rùi chỉ mình với
#include <18F4331.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
int i=0;
void main()
{
setup_timer_0(rtcc_div_32);
set_timer0(10); ????nếu đặt 1 thì bao lâu mới ngắt
enable_interrupts(int_rtcc);
enable_interrupts(global);
while(true)
{
}
}
#int_rtcc
void ngat_timer()
{
i++;
output_D(i);
}
cấu hỏi thứ 2 là khi giao tiếp máy tính mình truyền từ PC đến pic
dùng lệnh getc(); thì chỉ thu được 1 kí tự
ví dụ truyền số 12 thì thu được 2 số 1 và 2
có bạn nào biết lệnh nào để lấy 1 chuỗi ko?
namqn
18-07-2007, 06:56 PM
Về timer 0 và hàm set_timer0(), bạn đọc thêm tài liệu hướng dẫn của CCS C (trang 206, ver. 4, 01/2007) và datasheet của chip.
Về getc(), nếu bạn dùng nó thì tất nhiên chỉ lấy được 1 ký tự là nó đã trở về. Bạn đọc thêm về hàm gets() trong tài liệu hướng dẫn của CCS C (đã nêu trên, trang 148) để đọc 1 chuỗi ký tự.
Nếu bạn chưa biết tài liệu đó lấy ở đâu:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Thân,
anh_gioi
18-07-2007, 08:24 PM
cho em hỏi cái bài LCD ở trên mà em đã hỏi ý ạ.em đã cho hiển thị được rùi, nhưng :
khi chạy lượt đầu tiên thì nó bị mất 1 kí tự đầu tiên,ở cả 2 hàng luôn.và chạy lượt sau nó ko bị mất,đúng như lập trình.
em đã khai báo 0x80 và 0xc0 cho 2 hàng ạ
namqn
18-07-2007, 11:06 PM
cho em hỏi cái bài LCD ở trên mà em đã hỏi ý ạ.em đã cho hiển thị được rùi, nhưng :
khi chạy lượt đầu tiên thì nó bị mất 1 kí tự đầu tiên,ở cả 2 hàng luôn.và chạy lượt sau nó ko bị mất,đúng như lập trình.
em đã khai báo 0x80 và 0xc0 cho 2 hàng ạ
Mất theo kiểu nào vậy bạn? Không hiển thị ra ở vị trí đó hay là những ký tự nằm cùng hàng bị dịch qua bên trái một vị trí hay là hiển thị sai ở vị trí đó?
Thân,
anh_gioi
19-07-2007, 11:44 AM
dạ .LCD quét lần đầu tiên nó bị dịch sang trai 1 ki tu.(như : ANH_GIOI thì nó còn NH_GIOI).quét lần thứ hai thì nó ko bị mất như trên nữa.
e bị mất cả 2 hàng luôn mới đau chứ
namqn
19-07-2007, 06:19 PM
dạ .LCD quét lần đầu tiên nó bị dịch sang trai 1 ki tu.(như : ANH_GIOI thì nó còn NH_GIOI).quét lần thứ hai thì nó ko bị mất như trên nữa.
e bị mất cả 2 hàng luôn mới đau chứ
Hiện tượng này có nhiều khả năng là do thuật toán của bạn, lượt chạy đầu tiên con trỏ của chuỗi ký tự bị sai chẳng hạn. Bạn kiểm tra lại thuật toán của chương trình. Ở đầu vòng lặp chính nên có lệnh đặt giá trị cho con trỏ dùng để truy xuất chuỗi ký tự.
Thân,
nguyen.geo
19-07-2007, 10:10 PM
dạ .LCD quét lần đầu tiên nó bị dịch sang trai 1 ki tu.(như : ANH_GIOI thì nó còn NH_GIOI).quét lần thứ hai thì nó ko bị mất như trên nữa.
e bị mất cả 2 hàng luôn mới đau chứ
Ban ơi theo mình thì bạn hãy đặt giá trị trễ thêm 1 tí nữa là được thôi mình cũng đã gặp trường hợp nảy rồi lỗi này thường xuất hiện với các câu lệnh như là xóa màn hình, về đầu dòng, dịch con trỏ. Thưởng thì mình đặt trễ sau xóa màn hình 2ms, sau lệnh chức năng khác cho LCD ( Trường hợp RS = 0) là 10 us thì nó làm việc bình thường.các lệnh hiển thị dữ liệu thì không cần. Bạn thử theo cách của mình nhé. chúc bạn thành công !
tuanta
01-08-2007, 02:34 PM
Xin chào,
Mình đang sử dụng con PIC16F873A, chương trình viết trên CCS C. Mình gặp một lỗi rất khó hiểu là khi làm việc với portB, có duy nhất chân RB3 là mình không sao điều khiển được. Chẳng hạn mình dùng lệnh output_high(PIN_B3) thì không bao giờ nó High cả. Mạch test mình làm cũng rất đơn giản, giống như mạch của NHH post thôi. Mình đã nghĩ là do con PIC của mình nó hỏng riêng chân đấy, nên mình đã thử mua mấy con PIC16F873A khác về dùng, tình trạng vẫn hệt như vậy. Sau đó mình lại tiếp tục thử bằng cách chuyển sang con PIC16F876A xem sao, thì lỗi gặp cũng y hệt! Xin mọi người lời khuyên.
(Mạch nạp mình dùng là Galep-4).
Chào cả nhà!
Để lập trình cho PIC, mọi người có thể chọn cho mình những ngôn ngữ lập trình khác nhau như ASM, CCS C, HT-PIC, pascal, basic,...
Với nhh, đầu tiên tìm hiểu và viết chương trình cơ bản bằng ASM để hiểu rõ cấu trúc sau đó thì viết bằng CCS C cũng viết lại những cái cơ bản và đi dần lên, tốc độ lúc này nhanh hơn khi viết bằng ASM rất nhiều.
Khi viết bằng CCS C thông thường thì dịch ra file.hex có dài hơn so với khi viết bằng ASM. Hai ngôn ngữ CCS C và HT-PIC được ưa chuộng hơn cả, CCS C dễ học,gần gũi với ASM còn HT-PIC là dạng ANSI C.
Để lập trình và biên dịch CCS C, dùng chương trình PIC C Complier,sau khi soạn thảo các bạn ấn F9
để dịch,nếu thành công sẽ có thông báo như sau:
http://i82.photobucket.com/albums/j257/nhhao/ccsc.gif
Ngoài ra, để xem code ASM như thế nào,sau khi dịch bạn chọn mục C/ASM List như hình dưới đây:
http://i82.photobucket.com/albums/j257/nhhao/ccsc1.gif
Link download trình biên dịch CCS C ở đây: http://www.tailieuvietnam.net/download/PICSoft/CCSC_3.249.rar
Phiên bản mới hơn tải tại: www.kho.tailieuvietnam.net, vào Download Home > Điện tử tàn thư > Vi điều khiển - Vi xử lý - PLC
Chúng ta cùng nhau tìm hiểu lần lượt các phần sau:
1.I/O + Delay
2.Timer và ngắt Timer
3.Ngắt ngoài
4.ADC, PWM,... (tập trung mổ xẻ nhiều)
5......
Tạm thời cứ như vậy đã, sau này sẽ tính tiếp!
Nào,chúng ta bắt đầu thôi!
Chương trình này làm nhấp nháy con led ở chân RB0 1s sáng, 1s tắt.
#include<16F877A.h>
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=10000000)
main()
{
while(true)
{
output_high(PIN_B0);
delay_ms(1000);
output_low(PIN_B0);
delay_ms(1000);
}
}
Trên đây:
#include<16F877A.h>
Khai báo con PIC bạn sử dụng, file này chương trình viết sẵn nhằm khai báo các bit, thanh ghi quan trọng trong con pic này.Các bạn có thể vào thư mục cài đặt C:\Program Files\PICC\Devices\16F877A.h để xem nó khai báo được những gì trong đó!
#fuses NOWDT,PUT,HS,NOPROTECT
Thiết lập các config
#use delay(clock=10000000)
Khai báo tần số dao động cấp cho PIC
output_high(PIN_B0)
Xuất ra chân RB0 mức logic 1 (tức 5V), do khi thực hiện hàm này đã bao hàm luôn việc tác động lên thanh ghi TRISB (dùng chọn chân I/O) do vậy ta không cần viết lệnh chọn chân I/O nữa.
output_low(PIN_B0)
Ngược lại
delay_ms(1000)
Tạo trễ khoảng thời gian theo mili giây là 1000 (tức 1s)
Chú ý hàm này chỉ có tác dụng khi có khai báo tần số dao động cấp cho PIC
Và bây giờ thử làm cho tất cả 8 led nối với portB chớp tắt 1s xem nào!Phải chăng ta sẽ làm như sau (Viết trong vòng lặp while):
{
output_high(PIN_B0);
output_high(PIN_B1);
output_high(PIN_B2);
output_high(PIN_B3);
output_high(PIN_B4);
output_high(PIN_B5);
output_high(PIN_B6);
output_high(PIN_B7);
delay_ms(1000);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B3);
output_low(PIN_B4);
output_low(PIN_B5);
output_low(PIN_B6);
output_low(PIN_B7);
delay_ms(1000);
}
Viết như thế này thì quá dài và thiếu chính xác nữa, có cách nào khác hay hơn không ? Sao ta không xuất đẩy hẳn portB lên mức cao,tạo trễ 1s rồi ép cho nó xuống mức thấp,tạo trễ 1s cùng một lúc nhỉ !
Bài tiếp theo sẽ đưa ra câu trả lời....
http://www.freewebtown.com/nhhao/PIC/Delay%201s%20RB0.GIF
picpicpic
02-08-2007, 10:08 AM
Bạn chú ý chân RB3 là chân cực thu hở, muốn sử dụng, bạn mắc thêm 1 điện trở kéo lên.
chào các Bác mình mới học ccs c được vài ngày nhưng khi viết ct hiển thị trên 2 led 7 doan và mô phỏng trên proteus thì không được, mong các bác cho em đoạn code. cám ơn
sphinx9
09-08-2007, 04:12 AM
mấy anh cho em hỏi xíu ạ tại seo khi em xài các lệnh
trisb=0;
rb0=1;
rb1=1;
rb2=1;
rb3=1;
hoặc các lệnh:
output_high(pin_b0);
output_high(pin_b1);
output_high(pin_b2);
output_hgh(pin_b3);
mà nếu em gắn ở các chân đó là led thì nó sáng lần lược ở rb0 rb1 rb2 rb3 chứ nó ko sáng ở cả 4 chân bật debug của protus lên thì
trisb=0b11110000 : cái này thì đúng rùi
portb=0b00001000 : còn cái này seo kì wá
nhưng nếu em lắp vào đó dộng cơ thì lại khác em lắp vào rb0 động cơ ocn2 mấy cái kia là led thì động cơ way led ở rb3 sáng còn ở rb1 rb2 tắt
nhưng nếu em xài lệnh
portb=0b00001111; thì nó lại sáng bình thường
mấy anh giải thích giùm em với
cám ơn
dvnccbmacbt
12-08-2007, 12:09 AM
Chào mọi người! Em có 1 thắc mắc muốn hỏi : Với ngắt RB4-7 thì dòng lệnh ext_int_edge( H_to_L ) hình như không có tác dụng. Em thử bỏ hoặc thay thế bằng ( L_to_H ) thì thấy không có thay đổi gì. Hình như mặc định là H_to_L . Em có đọc trong datasheet PIC18f4550 thì chỉ thấy nói đến chọn cạnh lên xuống ở ngắt ngoài RB0, còn ở RB4-7 thì không thấy nói rõ. Em không hiểu rõ chỗ này. Mong mọi người chỉ bảo.
cuopbienquin
15-08-2007, 05:05 PM
Mình mới học về PIC.Cho hỏi ADC module có chức năng gì,công dụng ntn trên PIC? Mình nghĩ cho một điện thế analog thì nó xuất ra tín hiệu digital.Mình đã có đọc đoạn code này nhưng chưa hiểu rõ :
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#device 16F877*=16 ADC=8
#use delay(clock=10000000)
Int8 adc;
main()
{
setup_adc(adc_clock_internal);
setup_adc_ports(AN0);
set_adc_channel(0);
delay_ms(10);
while(true)
{
adc=read_adc();
output_B(adc);
}
}
Bạn nào đã đi trước thì giải thích giùm mình nhé,mình cần luôn file mô phỏng proteuss để hiểu rõ hơn.Cám ơn nhiều.Chúc vui.
thaithienanh
15-08-2007, 11:15 PM
To @c828 : việc quét 2 led rất đơn giản, chắc là do bạn chưa nắm đuợc quét led là gì rồi, bây giờ mình sẽ cho bạn một ví dụ cơ bản nhất về quét led (có kèm file Proteus và notepad), sau đó thì bạn nghiền ngẫm code khoảng vài phút chắc sẽ hiểu thui :)
To @sphinx9 : Cách diễn giải câu hỏi của bạn hơi khó hiểu một chút nhưng mình cũng loáng thoáng hiểu đuợc và xin trả lời là : đó là điểm yếu của Proteus nên không cần thắc mắc và cũng không thể giải thích :o (mình nói thật đó đừng nghe giọng văn trả lời cụt ngủn mà hiểu lầm nhá :D )
To @dvnccbmacbt : Ngắt RB dùng để ghi nhận sự kiện "có sự thay đổi bất kỳ" trên các chân từ RB4 đến RB7 cho nên việc chọn sườn ngắt không có vai trò ý nghĩa ở đây :o
To @cuopbienquin : ADC = Analog Digital Convert như vậy ý nghĩa của nó là một bộ chuyển đổi từ tín hiệu "tương tự" sang giá trị "số" tương ứng. Tuỳ vào việc lựa chọn điện áp tham chiếu và độ phân giải mà giá trị cho ra sẽ khác, ví dụ khi ta lựa chọn là ADC=8 và Vref = 5V thì khi đó nếu tín hiệu đưa vào bộ ADC là 5V thì giá trị số trả ra là 11111111 (8bit) = 255, công thức tổng quát lúc này sẽ là :
Value (giá trị "số") = 255 (max value của 8 bit) * X (tín hiệu đưa vào) / 5 (Vref)
Bạn tham khảo thêm tại bài trước nhá link đây :
http://www.picvietnam.com/forum//showthread.php?t=357&page=17
cuopbienquin
17-08-2007, 04:45 PM
PWm là bộ điều chế đọ rộng xung.Mình đang tìm hiểu cái module này nó hoạt độnh ntn?Mình đã đọc tổng quan về nó là dùng để điều khiển động cơ như tốc độ,tần số..
Mình muốn hiểu rõ hơn cấu trúc mạch ntn trong VDK PIC,kết nối với động cơ ra sao.BẠn nào đã tìm hiểu rồi thì hướng dẫn gíp mình nha.Mình đang rất cần.Chúc vui
huybo02
18-08-2007, 09:57 AM
Mình mới học về PIC.Cho hỏi ADC module có chức năng gì,công dụng ntn trên PIC? Mình nghĩ cho một điện thế analog thì nó xuất ra tín hiệu digital.Mình đã có đọc đoạn code này nhưng chưa hiểu rõ :
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#device 16F877*=16 ADC=8
#use delay(clock=10000000)
Int8 adc;
main()
{
setup_adc(adc_clock_internal);
setup_adc_ports(AN0);
set_adc_channel(0);
delay_ms(10);
while(true)
{
adc=read_adc();
output_B(adc);
}
}
Bạn nào đã đi trước thì giải thích giùm mình nhé,mình cần luôn file mô phỏng proteuss để hiểu rõ hơn.Cám ơn nhiều.Chúc vui.
ADC là chức năng chuyển đổi tín hiệu analog -> digital (Analog Digital Converter). Nó dùng 1 điện áp để so sánh (Vref) tùy độ phân giải mà điện áp này được chia là nhiểu mức khác nhau (2^n) với 16F877A ADC 10 bit tức Vref dc chia thành 2^10 = 1024 mức. Mỗi mức ADC cách nhau tương ứng với Vref/số mức. Vref = 5V thì mỗi mức ADC của 16F877 ứng với 5V/1024 = 4.88mV. Điện áp trên cổng AN sẽ được so sánh để ra được mức ADC tương ứng. 0V ứng với ADC =0, 4.88mV ứng với ADC =1...Kết quả được chứa trong 2 thanh ghi ADRESH:ADRESL.
Còn mạch cho code trên thì bạn mắc 1 cầu chia áp để đưa điện áp vào chân AN0 là được. Dùng biến trở cho gọn.
Còn PWM thì bạn đọc trong datasheet đó chương 8 phần CAPTURE/COMPARE/PWM MODULES và xem thêm bên ứng dụng điều khiển PID cho động cơ DC.
anh_gioi
21-08-2007, 08:38 PM
[QUOTE][QUOTE]
cho em hỏi] về đo nhiệt độ dùng pic 16f877A với ạ.code này em copy của anh linhnc308.nhưng về lắp vẫn chưa chay.trong code nó bị báo lỗi
[QUOTE] // trisa = 0xFF;
// trisb = 0x01;
// trisd = 0x00;[QUOTE]
em nghĩ là nó khai báo cho cổng ra vào nên em đã thay nó bằng :
set_tris_a(0xff);
set_tris_b(0x01);
set_tris_d(0x00);
thế là nó hết báo lỗi,nhưng vẫn ko đc.em đã lắp mạch thật cho nó nhưng nó vẫn im lìm ko báo biếc gì cả(bứ lắm cơ!)
các anh cho em lời khuyên với.
note: đây là mạch và code em mượn của anh linhnc308,mong anh cố gắng giúp cho kẻ ngốc nghếch này.em đã lắp mạch đúng,và mặc dù em đã lấy file hex của anh nạp vào mà nó vẫn im lìm ạ,
anh_gioi
21-08-2007, 08:44 PM
sao ko post file từ máy tính đc nhỉ? thui khi khác post sau vậy.lại vẫn dậm chân 1 chỗ.chán thật
cuopbienquin
22-08-2007, 06:18 PM
Đây là chương trình dùng ngắt Timer0 định thì 1s.
Đầu tiên led ở chân RB0 sáng, sau 1s sẽ dịch sang trái, nghĩa là led 1 trên chân RB1 sáng , lần lượt như vậy cho các led trên portB và lặp lại mãi mãi.
//************************************************** **
// Author : nhh
// Date : 02/04/06
// Hardware: PIC16F877A
//************************************************** **
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)
#byte portb=0x06
#define led pin_B0
int16 count;
int8 a;
//Chuong trinh ngat TMR0
#int_timer0
void interrupt_timer0()
{
set_timer0(6);
++count;
if(count==2000)
{
count=0;
a=a<<1; // dich trai a 1bit
}
if(a==256)
{
a=1;
count=0;
}
}
//Chuong trinh chinh
main()
{
set_tris_b(0);
enable_interrupts(global);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
set_timer0(6);
count=0;
a=1;
while(true)
{
portb=a;
}
}
http://www.freewebtown.com/nhhao/PIC/Nhay LED PortB.GIF
Mình đang học về Timer .Theo bài này thì khi với thạch anh 4Mhz thì thời gian cho mồi dòng lệnh là 100us hay sau 100us thì timer sẽ báo tràn và quay trở lại 0. Có phải biến count là gán cho "mỗi dòng lệnh",nghĩa là khi count=2000 <=>delay 2000x100us= 20s chứ không phải 1s.
Tiếp theo ,về vấn đề thanh ghi pres_scaler ,mình không hiểu chế độ div _2,div_ 4 ảnh hưởng thề nào tới thời gian thực thi mỗi dòng lệnh,timer làm việc ra sao???Mình cũng có đọc chế độ hoạt động và xem block diagram mà chả hiểu gì cả.Mong các bạn giúp đỡ.Chúc vui
dtdat1909
28-08-2007, 09:34 PM
không phải như bạn nghĩ đâu. mad thời gian định thời được tính theo công thức:
t=4*256*prescaler/Fosc
ở đây 4 hình như là số chu kỳ trong một lệnh đếm
prescaler là tỷ lệ mà ta quy định cho Timer, nó được xem là clock cho timer khi timer đếm(tần số dùng để đếm cho Timer bằng OSC/prescaler).
Fosc là tần số xung clock cung cấp cho mạch.
khi viết rtcc_div_2 có nghĩa là: tần số cung cấp cho bộ đếm Timer0 bằng
Fosc/2.
cuopbienquin
29-08-2007, 09:16 PM
Đây là mã code mình viết ngắt đơn giản cho LCD.Khi nhấn button 1(RB4) thì LCD hiển thị chữ 'X' dòng 1,button 2 thì LCD hiển thị dòng 2 chữ 'K'.Nhưng khi chạy thì nó bào lỗi ở dòng "void main(void)" là 'A numeric expression must be here'
================================================== ===========================*/
#include <16F877A.h>
#include <DEFS_16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define RS RD0
#define RW RD1
#define E RD2
#define LCD PORTC
/*Ham yeu cau goi lenh dieu khien LCD*/
void comnwrt(void)
{
RS = 0;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
/*Ham yeu cau goi du lieu hien thi len LCD*/
void datawrt(void)
{
RS = 1;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
#int_RB
void ngat_RB(void)
{
if(RBIE && RBIF)
{
if (RB4==0)
{
while(RB5==1)
{
LCD = 0x83;
comnwrt();
LCD = 'X';
datawrt();
}
}
if (RB5==0)
{
while(RB4==1)
{
LCD = 0xC3;
comnwrt();
LCD = 'K';
datawrt();
}
}
}
void main(void)
{
set_tris_b(0b01100000);
set_tris_c(0);
set_tris_d(0);
LCD = 0x38; // Hai hang, ma tran dot 5*7, 8 bit interface
comnwrt();
LCD = 0x0C; // Bat hien thi, tat con tro
comnwrt();
while(true)
{
}
}
namqn
29-08-2007, 11:56 PM
Khi chạy chương trình đó bạn nhận được thông báo lỗi đó? Thông báo lỗi đó xuất hiện ở đâu?
Nếu bạn chạy chương trình với phần cứng của bạn theo cách thông thường, chỉ có bộ vi điều khiển và LCD, bộ phận hiển thị duy nhất mà bạn có là màn hình LCD, làm cách nào bạn nhận được thông báo lỗi đó, khi LCD chưa hoạt động đúng.
Tôi đoán là bạn muốn nói khi biên dịch chương trình thì nhận được thông báo lỗi đó. Bạn xem thử các ví dụ mẫu của CCS C để biết người ta khai báo main() ra sao. Bạn cũng kiểm tra lại code xử lý ngắt RB của bạn, dường như bạn đang thiếu một dấu '}'.
Thân,
thaithienanh
30-08-2007, 12:55 AM
Bạn phạm phải trọng tội rùi chắc hình phạt phải là "tử hình" thui đó mà :D
Lỗi của bạn là thiếu một dấu móc khoá "}" ở cuối hàm, ngay trên void main ấy thêm vào là OK :D
Lần này tha lần sau là tử hình thiệt đó nghen :D .
Thân.
cuopbienquin
30-08-2007, 12:42 PM
Cám ơn các bạn nhiều,mình đã biết sai rồi.Nhưng khi mô phỏng bằng Proteuss thì không như ý muốn,LCD cứ lặng thinh.Đây là mạch mô phỏng
http://i190.photobucket.com/albums/z275/rosanhdieu/NEWLCD.jpg
code:#include <16F877A.h>
#include <DEFS_16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define RS RD0
#define RW RD1
#define E RD2
#define LCD PORTC
/*Ham yeu cau goi lenh dieu khien LCD*/
void comnwrt(void)
{
RS = 0;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
/*Ham yeu cau goi du lieu hien thi len LCD*/
void datawrt(void)
{
RS = 1;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
#int_RB
void ngat_RB(void)
{
if(RBIE && RBIF)
{
if (RB4==0)
{
while(RB5==1)
{
LCD = 0x83;
comnwrt();
LCD = 'X';
datawrt();
}
}
if (RB5==0)
{
while(RB4==1)
{
LCD = 0xC3;
comnwrt();
LCD = 'K';
datawrt();
}
}
}
}
void main(void)
{
set_tris_b(0b00110000);
set_tris_c(0);
set_tris_d(0);
LCD = 0x38; // Hai hang, ma tran dot 5*7, 8 bit interface
comnwrt();
LCD = 0x0C; // Bat hien thi, tat con tro
comnwrt();
while(true)
{
}
}
Mình làm mạch này chủ yếu để hiểu cơ bản và tiếp tục làm phần kết hợp keypadphone và LCD ,mạch nhu cầu như sau
http://i190.photobucket.com/albums/z275/rosanhdieu/LCDkey2.jpg
Mình cần :nhấn phím trên keypad thì LCD sẽ hiển thị trên LCD và khi nhấn button thì nó xóa một ký tự hiển thị .Mình có tham khảo source code trong CCS nhưng chả biết dùng như thế nào,đây là code ứng dụng:
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <lcd.c>
#include <kbd.c>
void main() {
char k;
lcd_init();
kbd_init();
lcd_putc("\fReady...\n");
while (TRUE) {
k=kbd_getc();
if(k!=0)
if(k=='*')
lcd_putc('\f');
else
lcd_putc(k);
}
}
cuopbienquin
31-08-2007, 11:13 AM
Xin lỗi mình pót bài này mà không thấy bác nào trả lời giùm .Có lẽ do nhiều luồng mới quá nên các bác không để ý.Hôm nay mình post lại vậy.Mình có cuốn Interfacing PIC nhưng viết bằng ASM,mà mình thì đang cần C.Không biết bác nào có sách Interfacing PICmaf viết bằng C khồng nhỉ?
thaithienanh
31-08-2007, 09:36 PM
Bạn Cướp biển chuẩn bị chạy trước đi nhé, mình đã "lắp đạn vào súng" rùi đây này :cool:
Do bạn phạm các tội sau :
- Chưa khai báo cho phép ngắt RB ở void main : phải thêm vào đó 2 dòng : enable_interrupts(global);
enable_interrupts(int_RB);
- Ở trên mạch ứng dụng chẳng thấy điện trở treo lên nguồn đâu nữa
Tài liệu thì mình không có và rất ít đọc (do lười :p )
Nhưng góp ý thế này : muốn học từ Sample của CCS thì phải :
Bạn mở code cái Driver mà CCS hỗ trợ lên, đọc kỹ định nghĩa của các hàm mà Driver hỗ trợ (để khi dùng thì gọi ra trong chương trình), xem Driver đó sử dụng những chân nào của VDK, nối đúng chân mà dùng :)
cuopbienquin
31-08-2007, 11:55 PM
chà mình đã chuẩn bị chạy rồi .mình biết sau khi mình post bài mình đã thiếu yêu cầu như bạn comment và vẽ lại mạch mô phỏng như bạn nhắc nhở.Nhưng vẫn cứ lặng thinh.Mong bạn và các bạn trong diễn đàn chạy thử lại và test giùm mình như bạn đã nói,và cùng correct lại mạch và code như yêu cầu mình mong muốn xem sao.Còn về ứng dụng trong CCS ,rất phức tạp.Mình muốn tự mình lập trình theo yêu cầu ,post code xem mình sai đúng chỗ nào,để sữa lỗi và tiện học hỏi luôn như vạy dễ hiểu hơn.Mong các bạn thông cảm .Chúc vui
thaithienanh
01-09-2007, 12:24 AM
Đã test lại giúp bạn, tất cả đều ổn, mình gửi luôn cái hình để bạn xem lại, còn về code mình chỉ thêm đúng vào 2 câu mà mình đã nói ở trên :)
cuopbienquin
01-09-2007, 05:02 PM
Mình thật sự cảm ơn bạn thaithienthanh rất nhiều về vấn đề này.Mình đã làm lại và chạy ngon lành.Nhưng để thực tế hơn mình đã làm một cái keypadcalulate thay cho mấy cái button .Mạch như sau:
http://i190.photobucket.com/albums/z275/rosanhdieu/LCD3.jpg
Code:#include <16F877A.h>
#include <DEFS_16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define RS RD0
#define RW RD1
#define E RD2
#define LCD PORTC
/*Ham yeu cau goi lenh dieu khien LCD*/
void comnwrt(void)
{
RS = 0;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
/*Ham yeu cau goi du lieu hien thi len LCD*/
void datawrt(void)
{
RS = 1;
RW = 0;
E = 1;
E = 0;
delay_ms(1);
}
#int_RB
void ngat_RB(void)
{
if(RBIE && RBIF)
{
//hang A
if ((RB0) && (RB4))
{
LCD = '7';
datawrt();
}
if (RB0 && RB5)
{
LCD = '8';
datawrt();
}
if (RB0 && RB6)
{
LCD = '9';
datawrt();
}
if (RB0 && RB7)
{
LCD = ':';
datawrt();
}
//Hang B
if ((RB1) && (RB4))
{
LCD = '4';
datawrt();
}
if (RB1 && RB5)
{
LCD = '5';
datawrt();
}
if (RB1 && RB6)
{
LCD = '6';
datawrt();
}
if (RB1 && RB7)
{
LCD = 'x';
datawrt();
}
//Hang C
if ((RB2) && (RB4))
{
LCD = '1';
datawrt();
}
if (RB2 && RB5)
{
LCD = '2';
datawrt();
}
if (RB2 && RB6)
{
LCD = '3';
datawrt();
}
if (RB2 && RB7)
{
LCD = '-';
datawrt();
}
//Hang D
if ((RB3) && (RB4))
{
LCD = 0x0C;
comnwrt();
}
if (RB3 && RB5)
{
LCD = '0';
datawrt();
}
if (RB3 && RB6)
{
LCD = '=';
datawrt();
}
if (RB3 && RB7)
{
LCD = '-';
datawrt();
}
}
}
void main(void)
{
set_tris_b(0b00001111);
set_tris_c(0);
set_tris_d(0);
portb=0;
portc=0;
portd=0;
enable_interrupts(global);
enable_interrupts(int_RB);
ext_int_edge(H_TO_L);
LCD = 0x38; // Hai hang, ma tran dot 5*7, 8 bit interface
comnwrt();
LCD = 0x0C; // Bat hien thi, tat con tro
comnwrt();
while(true)
{
}
}
Khi compile thì chương trình dịc ok nhưng khi mô phỏng mình lại thấy LCD tiếp tục đứng im .Hee, mong các bạn tiếp tục giúp đỡ cho trọn vẹn nha.
Mình làm về project này là để làm một cái smallcal có dạng như trên hình vẽ, mình cùng đang tìm hiểu thuật toán của nó,đây là thuật toán trong sách Interfacing PIC về các phép tình đơn giản:
Calculate result
IF key = ‘+’, Add
IF key = ‘-‘, Subtract
IF key = ‘x’, Multiply
IF key = ‘/’, Divide
Add Add Num1 + Num2
Load result, CALL Two digits
Subtract Subtract Num1 – Num2
IF result negative, load minus sign, CALL Display character
Load result, CALL Display character
Multiply
REPEAT
Add Num1 to Result
Decrement Num2
UNTIL Num2= 0
Load result, CALL Two digits
Divide
REPEAT
Subtract Num2 from Num1
Increment Result
UNTIL Num1 negative
Add Num2 back onto Num1 for Remainder
Load Result, CALL Display character
Load Remainder, CALL Display character
Two digits
Divide result by 10, load MSD, CALL Display character
Load LSD, CALL Display character
Mình viết bằng ASM thì được chứ còn CCS thì non tay lắm .Mong các bạn giúp đỡ mình hoàn thành project này.Cảm ơn nhiều.Chúc vui.
cuopbienquin
05-09-2007, 11:26 AM
Đã lâu rồi mà không thấy các bác trả lời giùm nhỉ.mình sốt ruột quá
Mr.Bi
11-09-2007, 06:49 PM
Chả có gì là im re hết bạn ah ! nó vẫn chạy đấy nhưng bạn ko nhìn thấy thui ! Lý do : chân Vss của LCD bạn đã mắc luôn vào Mass , mình chưa thử kiểu mới này nhưng .. mình đoán nó sáng ngời hoặc túi thui luôn . Nhà sx đưa cho ta chân Vss là để chỉnh độ sáng của LCD . BẠn phải mắc 1 con trở tinh chỉnh cỡ 5k vào đó , sau đó chỉnh độ sáng yếu đi thì mới thấy kí tự hiển thị đc chứ ! ĐÚng ko ?
cuopbienquin
11-09-2007, 10:11 PM
thế ah,nhưng mình sữa lại như bạn nói mà không sáng.Vậy bạn có thể test giùm mình không?
Mr.Bi
12-09-2007, 12:31 AM
Đừng nôn nóng : Bạn đang đi đúng hướng đấy , Không phải xoay vài 3 vòng là thấy ngay đâu ? Tui xoay phải cỡ 7 vòng cơ đấy . Xoay kiểm tra theo 2 chiều . Cứ coppy nguyên code hiển thị LCD vào , sau đó chỉnh độ sáng của LCD chắc chắn bạn sẽ thấy Kí tự . Tui cũng điên đầu cho cái LCD này cả buổi tối đó .
thaithienanh
12-09-2007, 07:49 PM
Hix hix nghe hai bạn trao đổi với nhau mà đâu óc mình lùng bùng quá giờ mình hết hiểu gì hết luôn rồi :confused: . VSS nối với nguồn âm thì quá đúng rùi đâu có gì sai đâu :confused: , còn chân VEE thì ở một số LCD ta thấy nó còn có tên khác là V0 : chân này có tác dụng là điều chỉnh độ tương phản trên LCD, vì vậy ở chân này nguời ta thường đấu vào đó một biến trở để điều chỉnh điện áp, dao động trong khoảng từ 0 --> 5V, trong lúc test có thể đấu trực tiếp xuống nguồn âm cũng đuợc :o .
Còn về phần lý do tại sao cái LCD của bạn không hiển thị là do cà hai lỗi thiết kế phần cứng và phần mềm luôn :D , cụ thể ở đây là về cách quét phím : Như mình nhận thấy ý đồ của bạn ở đây là set PortB từ chân RB0 --> RB3 là ngõ ra, còn lại là ngõ vào, khi ấn nút thì trình sẽ trôi vào hàm ngắt, ở đó bạn sẽ test xem mức áp ở các chân của matrix mà suy ra phím nào đã bấm đúng không ;) => Ý đồ có những sai lầm như sau :D :
1. Set Port của bạn bị ngược, đây là cái sai cơ bản nhé ;)
2. Giải thuật quét phím này về cơ bản sai hoàn toàn bởi lẽ : khi bạn đã set chân là ngõ ra thì làm sao mà bạn có thể đọc đuợc giá trị từ nó về :D
Ở đây vì để cho bạn tự học, tự phát huy khả năng của mình là chính cho nên mình chỉ đưa ra cho bạn giải thuật để giải quyết vấn đề thui, tuyệt không thể trực tiếp viết code giùm bạn đuợc ;) :
- Cách quét phím : bạn thực hiện set Port có 4 ngõ ra và 4 ngõ vào : bây giờ ví dụ các chân ra là từ 1-->4, các chân vào là từ 5-->8 nhé, quy trình quét như sau :
Xuất áp ra chân 1 -> test áp ở chân 5 (gán giá trị cố định vào đó và kết hợp hiển thị LCD),6(...),7(...),8(...), đưa áp chân này về mức cũ ; Xuất áp ra chân 2 -> test áp ở 5(...),6(...),7(...),8(...) ; ..... như vậy bạn sẽ đuợc một ma trận phím quét và hiển thị ra LCD, => mấu chốt cách quét này là gì ?: đó là lợi dụng khả năng chủ động của mình khi cố ý xuất áp ra một chân và kiểm tra mức áp ở 4 chân còn lại => đây là cách quét phím cơ bản nhất :) .
Trong đó có một phím xoá cả màn hình bạn dùng lệnh : LCD=0x01;comnwrt() ;) ;
Còn về phép tính bạn có thể viết cho nó một hàm tính toán riêng : khai báo 4 biến là a,b,pheptinh,ketqua --> sau mỗi lần đọc đuợc giá trị từ phím về thì gửi giá trị vào hàm này và lựa chọn nhét vào biến a hay b (nhét vào a khi chưa ấn các phím phép tính +,-,… Và vào b sau khi đã ấn), công việc là phải sắp xếp các giá trị nhét vào này thành hai con số a và b hẳn hòi (như vậy a và b cũng cần có hàm con để thực hiện sắp xếp, gợi ý như sau :bạn dùng biến count trong này sau mỗi lần value đuợc đưa vào thì biến này sẽ thay đổi do đó dữ liệu căn theo đó mà sắp xếp), xong lúc này chỉ việc chờ phím "=" là ta sẽ đem a (+,-... căn cứ vào biến pheptinh) cho b để ra c sau đó đem c hiển thị lên LCD là xong :p .
Thú thật mình chưa làm cái này bao giờ nên chỉ thực hiện sơsài để có thể hướng dẫn đuợc cho bạn thui, có gì thiếu sót thì bỏ quá cho vậy, dưới đây là hình ảnh về phần cứng để bạn hiểu hơn :) :
Bạn sẽ thành công nếu như bạn cố gắng hơn nữa, phát huy tối đa khả năng của mình :), từ từ sẽ có kinh nghiệm, mong rằng sau này có dịp mình sẽ học hỏi lại :p
Thân.
thobnvn87
13-09-2007, 12:13 PM
các bac ơi giup em voi đưoc khong ạ? em dang phai lam 1 bai tap: tim hieu ve net matrix xem no hoat dông the nào? ma chua biet lam ra sao day.bac nao biet giup em voi nha chieu nay em phai nop bai roi.thank cac bac nhieu
cuopbienquin
14-09-2007, 01:20 PM
Bạn đọc ơ luồng này ở page 2 hay 3 gì có nói đó.Chúc vui
nbchien
21-09-2007, 03:36 PM
Ngắt Timer0
Đây là chương trình dùng ngắt Timer0 định thì 1s.
Đầu tiên led ở chân RB0 sáng, sau 1s sẽ dịch sang trái, nghĩa là led 1 trên chân RB1 sáng , lần lượt như vậy cho các led trên portB và lặp lại mãi mãi.
Code:
//************************************************** **
// Author : nhh
// Date : 02/04/06
// Hardware: PIC16F877A
//************************************************** **
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(b)
#byte portb=0x06
#define led pin_B0
int16 count;
int8 a;
//Chuong trinh ngat TMR0
#int_timer0
void interrupt_timer0()
{
set_timer0(6);
++count;
if(count==2000)
{
count=0;
a=a<<1; // dich trai a 1bit
}
if(a==256)
{
a=1;
count=0;
}
}
//Chuong trinh chinh
main()
{
set_tris_b(0);
enable_interrupts(global);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
set_timer0(6);
count=0;
a=1;
while(true)
{
portb=a;
}
}
Ai hiểu chương trình trên giải thích hộ em với ạ:
Thứ nhất khi nào hàm con interrupt_timer0() được gọi
Thứ hai, việc tính toán định thì 1s được tính như thế nào.
Thứ ba, biến a được khai báo là số nguyên 8bit. Phạm vi từ 0->255,làm sao bằng 256 đc.
Em mới học nên kô biết, mong mọi người chỉ giúp. Thanks!
Thứ nhất khi nào hàm con interrupt_timer0() được gọi
Thứ hai, việc tính toán định thì 1s được tính như thế nào.
Thứ ba, biến a được khai báo là số nguyên 8bit. Phạm vi từ 0->255,làm sao bằng 256 đc.
1. Ngắt Timer0 được gọi khi Timer 0 bị tràn từ 0xff sang 0x00 với điều kiện phải có 2 khai cho phép ngắt timer 0 và ngắt toàn cục:
enable_interrupts(int_timer0);
enable_interrupts(global);
2. Việc tính toán thời gian tràn của Timer rất dễ, xem luồng "PIC6f877A từ dễ tới khó", hoặc tìm đâu đó trong diễn đàn này phần mềm "PIC Timer Calculator".
3. Biến a 8bit int, ko thể có giá trị 256 -> đúng vậy.
#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#byte PORTB = 0x06
int16 count;
int8 a;
//Chuong trinh ngat TMR0
#int_timer0
void interrupt_timer0()
{
set_timer0(6);
++count;
if(count == 2000) // 2000*500us = 500000us = 1s
{
count=0;
rotate_left(&a,1);
}
}
//Chuong trinh chinh
void main(void)
{
set_tris_b(0);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
enable_interrupts(global);
set_timer0(6);// T_dinhthi = 2*(256 - 6)*1us = 500us
a = 0x01;
while(true)
{
PORTB = a;
}
}
P/S: Khi post chương trình, bạn nên sử dụng thẻ CODE #.
nguyenvo
22-09-2007, 12:13 PM
hi!các ban có chương trình hướng dẫn từ a-z của trình biên dịch asm không?thank
Ban co the giup 123? tai sao minh bo cai program nay vao complier thu, tra loi rang, unknow device, try dung pcm, nghia la sao? minh dung ccs 3.2. xin vui long giup dum minh
Đây là 1 ví dụ nhỏ về ADC,chân RA0 lấy tín hiệu Analog từ biến trở và xuất giá trị số biến đổi tương ứng qua tám led nối ở portB
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#device 16F877*=16 ADC=8
#use delay(clock=10000000)
Int8 adc;
main()
{
setup_adc(adc_clock_internal);
setup_adc_ports(AN0);
set_adc_channel(0);
delay_ms(10);
while(true)
{
adc=read_adc();
output_B(adc);
}
}
http://www.freewebtown.com/nhhao/PIC/ADC.GIF
nbchien
24-09-2007, 04:01 PM
Cảm ơn bác nhh đã trả lời câu hỏi của em. Bác có thể viết tiếp 1 chương trình đếm số xung đưa vào PIC trong 1 thời gian nhất định (1s chẳng hạn) để em và mọi người cùng tham khảo được không ạ?
funnyCat
24-09-2007, 10:16 PM
Các bác cho em hỏi là trong CCS làm sao có thể sử dụng được mảng nhiều phần tử cho PIC16F877a(em muốn dùng mảng khoảng 128 phần tử, nhưng chỉ khai báo được khoảng 93-94 phần tử thì nó báo là ko đủ RAM)
funnyCat
24-09-2007, 10:19 PM
À quên, em khai báo 4 mảng 60 phần tử thì lại được. Làm sao để gộp lại được thành 1 mảng nhỉ?
namqn
24-09-2007, 10:36 PM
Các bác cho em hỏi là trong CCS làm sao có thể sử dụng được mảng nhiều phần tử cho PIC16F877a(em muốn dùng mảng khoảng 128 phần tử, nhưng chỉ khai báo được khoảng 93-94 phần tử thì nó báo là ko đủ RAM)
À quên, em khai báo 4 mảng 60 phần tử thì lại được. Làm sao để gộp lại được thành 1 mảng nhỉ?
Bạn đọc datasheet của PIC16F877A, hình 2-3 (bản đồ bộ nhớ thanh ghi) sẽ thấy vùng RAM mà người sử dụng có thể đọc/ghi tùy ý (công dụng chung) được chia thành 4 bank không liên tục. Do đó hai trường hợp mà bạn đã gặp là hợp lý. Bạn được phép có 4 mảng, mỗi mảng có tối đa 80 byte, chứ không thể có một mảng liên tục như bạn yêu cầu. Trình dịch cũng khó mà làm gì hơn được vì cấu trúc của RAM trong chip là như vậy. Các PIC18 có bộ nhớ RAM rộng rãi và liên tục hơn nhiều.
Thân,
nbchien
25-09-2007, 03:03 PM
Cảm ơn bác nhh đã trả lời câu hỏi của em. Bác có thể viết tiếp 1 chương trình đếm số xung đưa vào PIC trong 1 thời gian nhất định (1s chẳng hạn) để em và mọi người cùng tham khảo được không ạ?
Sao chẳng thấy ai có ý kiến j nhỉ? Các cao thủ đâu hết rồi!
vuongctho
26-09-2007, 11:21 PM
em dang hoc lap trinh c cho pic, a nao co tai lieu tieng viet huong dan lap trinh css cho pic cho e xin voi!!!!hepl!
cho em hoi!em muon lam lich van nien viet phan mem bang ccs,cac "thay" nao da tung lam roi cho em biet minh lam ntn voi??huong dan em viet ccs cho mach nay voi!!!cam on!!!!
tungtot_vl
28-09-2007, 08:28 AM
các anh ơi cho em hỏi cái này tí
em dùng ccs để lập trình cho bài led matrix. em mới mã hóa font cho vài từ thì chương trình đã báo là không đủ RAM.
thế làm cách nào để nâng cấp thêm RAM cho CCS hả các anh.
còn về phần cứng em cũng chưa biết dùng RAM gì cho đủ để mã hóa toàn bộ font cho đủ. còn cách giao tiếp với RAM ngoài thì thế nào em cũng chưa biết. các anh chỉ giúp em nhé.
vì em đang ở tp qui nhơn nên không có điều kiện họi hỏi mong các anh giúp đỡ
thế làm cách nào để nâng cấp thêm RAM cho CCS hả các anh.
Trình biên dịch chẳng liên quan gì đến RAM của chip cả.
Xin hỏi bạn dùng con pic nào? Với ứng dụng ko lớn thì 16F877A (887A) dùng thoải mái.
Nếu ko đủ thì bạn có thể lựa chọn chip có dung lượng lớn hơn, pic18F chẳng hạn.
namqn
28-09-2007, 06:42 PM
các anh ơi cho em hỏi cái này tí
em dùng ccs để lập trình cho bài led matrix. em mới mã hóa font cho vài từ thì chương trình đã báo là không đủ RAM.
thế làm cách nào để nâng cấp thêm RAM cho CCS hả các anh.
còn về phần cứng em cũng chưa biết dùng RAM gì cho đủ để mã hóa toàn bộ font cho đủ. còn cách giao tiếp với RAM ngoài thì thế nào em cũng chưa biết. các anh chỉ giúp em nhé.
vì em đang ở tp qui nhơn nên không có điều kiện họi hỏi mong các anh giúp đỡ
Để mã hóa font cho các ứng dụng led ma trận thì người ta thường dùng flash (bộ nhớ chương trình), vì RAM trên chip không nhiều và việc sử dụng RAM làm bảng mã hóa là sử dụng không đúng mục đích.
Thân,
tungtot_vl
01-10-2007, 09:30 AM
Để mã hóa font cho các ứng dụng led ma trận thì người ta thường dùng flash (bộ nhớ chương trình), vì RAM trên chip không nhiều và việc sử dụng RAM làm bảng mã hóa là sử dụng không đúng mục đích.
Thân,
lại làm phiền anh nam nữa rồi.
anh nam ơi vì em học lập trình qua mạng nên kinh nghiệm còn non lắm. từ trước đến giờ em chỉ biết xuất dữ liệu trực tiếp ra port thôi. em chưa biết cách lưu data vào flash như thế nào. em nhờ anh chỉ cho vài đường để hiểu biết thêm. em dùng pic 877. và trình dịch ccs
thank you
pic xuất hiện đầu tiên tại thành phố qui nhơn
tungtot_vl
01-10-2007, 04:53 PM
ai giải thích cho mình cái này nhỉ
khi dùng : unsigned char font[] = {...}; thì chương trình báo lỗi không đủ RAM
khi dùng : unsigned char const font[] = {...}; thì chương trình hết báo lỗi và dung lượng RAM giảm xuống rất nhiều.
mong giúp đỡ
nbchien
02-10-2007, 03:28 PM
Sao luồng này trầm thế nhỉ. Lâu lâu không thấy các cao thủ post bài cho bọn đàn em học tập với nhỉ
thaithienanh
03-10-2007, 12:43 AM
ai giải thích cho mình cái này nhỉ
khi dùng : unsigned char font[] = {...}; thì chương trình báo lỗi không đủ RAM
khi dùng : unsigned char const font[] = {...}; thì chương trình hết báo lỗi và dung lượng RAM giảm xuống rất nhiều.
mong giúp đỡ
:) Với cách khai báo thứ nhất sẽ có ý nghĩa là một mảng biến có kiểu ký tự cho nên dung lượng Ram lúc này sẽ tốn rất đáng kể.
Còn với cách khai báo thứ hai sẽ chỉ là một mảng các hằng số kiểu ký tự mà thôi cho nên việc bạn nhìn thấy dung lượng Ram giảm xuống rất nhiều là điều bình thường :)
thaithienanh
03-10-2007, 01:06 AM
Cảm ơn bác nhh đã trả lời câu hỏi của em. Bác có thể viết tiếp 1 chương trình đếm số xung đưa vào PIC trong 1 thời gian nhất định (1s chẳng hạn) để em và mọi người cùng tham khảo được không ạ?
Ừhm với câu hỏi này bạn có thể tham khảo qua ví dụ của anh Linh :)
thongtr
08-10-2007, 02:50 AM
Em vừa mới viết xong ct hiển thị LCD 4 bit! có hiệu ứng chữ chạy rất hay!! em post lên cho các pác tham khảo nhé! và góp ý cho em nhé!
#include <16F877A.h>
#include <DEFS_16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define use_portb_lcd TRUE
#include <lcd.c>
const unsigned char line1[]={'H','E','L','L','O',' ','P','I','C','V','N','!','#'};
const unsigned char line2[]={'Y','H',':','T','H','O','N','G','T','R','0','6', '0','1','@',\
'Y','A','H','O','O','.','C','O','M','#'};
void main(void)
{ while(true)
{
int I=0,y=0,k=0,z=0;
delay_ms(100); // tao tre 100ms cho LCD khoi dong
lcd_init();
lcd_gotoxy(1,1);
while (line1[y]!='#')
{
lcd_putc(line1[y]);
delay_ms(200);
y++;
}
lcd_gotoxy(1,2);
while (i<16)
{
lcd_putc(line2[I]);
i++;
delay_ms(200);
}
i=2;
while (line2[z]!='#')
{
lcd_init();
lcd_gotoxy(1,1);
y=0;
while (line1[y]!='#')
{
lcd_putc(line1[y]);
y++; }
lcd_gotoxy(1,2);
k=i+16;
for(z=i;z<k;z++)
{lcd_putc(line2[z]);}
delay_ms(400);
i++;
}
}
}
Nguoidumuc204
11-10-2007, 09:14 AM
Mình thấy khai báo mảng của bạn hơi phức tạp , sao không khai báo là
const unsigned char line1[]={"Hello PICVIETNAM#"};
const unsigned char line2[]={"YH :xxx"};
vậy thì đơn giản, dễ hiểu và kết quả vẫn vậy.
và hàm lcd_init(); chỉ cần dùng một lầm duy nhất là đủ,như vấy sẽ không làm cho lcd bị nháy khi hiển thị các câu khác nhau. Nếu muốn xóa trắng màn hình thì chỉ việc dùng lệnh lcd_putc("\f");
Nguoidumuc204
11-10-2007, 09:29 AM
Có cao thủ nào có thể cho em biết công thức liên hệ giữa Resolution và Overflow trong con PIC 16F877A không?
Em dùng thạch anh 4Mhz, timer0 , Resolution : 8us, Overflow : 2ms. Nhưng em không hiểu chúng liên hệ với nhau thế nào.
Em mới ra nhập làng VDK nói chung và Pic nói riêng,mong các bác giúp đỡ.
Nguoidumuc204
11-10-2007, 11:16 AM
Có cao thủ nào có thể cho em biết công thức liên hệ giữa Resolution và Overflow trong con PIC 16F877A không?
Em dùng thạch anh 4Mhz, timer0 , Resolution : 8us, Overflow : 2ms. Nhưng em không hiểu chúng liên hệ với nhau thế nào.
Em mới ra nhập làng VDK nói chung và Pic nói riêng,mong các bác giúp đỡ.
Chờ cả buổi mà chẳng bác nào tra lời,đi ăn xin nhiều nơi mới hiểu ra, thôi thì cứ POST lên cho anh em nào chưa rõ thì coi.
Timer0 là bộ định thời có khoảng chia cho trước , các khoảng chia theo 2 lũy thừa 1 2 4 8 ... ( tùy theo chip )
Ví dụ ở câu hỏi trên của em thì câu lệnh
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); // Prescale 4us,Overflow 2us
có nghĩa là :
cứ 4us ( 4 xung đồng hồ ) ==> 1 xung timer
cứ 255 xung timer ( 8 bit ) ==> 1 lần tràn
==> timer sẽ tràn từ 0xFF -> 0x00 trong khoảng thời gian 4 x 255 = 1020 us
Sangcao
11-10-2007, 02:57 PM
Bác nào giúp em với:! Em muon truyền 1 tín hiệu 4 - 20mA bằng dây dẫn khoảng cách 1000m, đang định sd 485 nhưng nghe có vẽ ko ổn lắm, sợ nhiễu. tín hiệu thu về cũng là 4-20mA. Ko biết bác nào có cánh hay hơn ko thì giúp mình với! cảm ơn nhiều nhé!
vandungevn
11-10-2007, 05:03 PM
Timer có nhiều kiểu chia tần, dùng chia trước và sau (prescale và postscale)
là chia trước và chia sau, có nhiều cách đặt tỉ lệ cho Timer từ 1:1 - 1:256 tức là cách chia này giúp cho ta nhận được xung kích vào Timer sẽ được chậm đi n lần ( 1:n ) so với 1Tcy (Fosc/4), và như vậy ta sẽ được xung kich chậm hơn:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); // 4Mhz => dùng dao động nội, chế độ prescal 1:4 => clock cho Timer0 la Fosc/4/4 = Fosc/16.
Khi này ta có Fosc/4 => Tcy = 1us. Ttimer0 = Fosc/16 => 4us
Timer0 tràn 8 bit => 4x8bit = 1024us.
8 bit có 256 trạng thái chứ không phải 255 trạng thái, do đó x256,
Còn cách thứ 2 Postscale (Only Timer2) thì nó sẽ đếm số lần tràn của Timer2,
Nghĩa là
1:2 - 2 làn tràn cho ra 1 lần xung .....
1:16 - 16 làn Timer2 tràn
giả sử Áp dụng với Timer2 thay Timer0 ở trên và với postscale 1:8 ta sẽ thu được đầu ra là : 4x256x8 = 8192 us
cooloo
12-10-2007, 12:59 AM
Chương trình này làm nhấp nháy con led ở chân RB0 1s sáng, 1s tắt.
#include<16F877A.h>
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=10000000)
main()
{
while(true)
{
output_high(PIN_B0);
delay_ms(1000);
output_low(PIN_B0);
delay_ms(1000);
}
}
Trên đây:
#include<16F877A.h>
Khai báo con PIC bạn sử dụng, file này chương trình viết sẵn nhằm khai báo các bit, thanh ghi quan trọng trong con pic này.Các bạn có thể vào thư mục cài đặt C:\Program Files\PICC\Devices\16F877A.h để xem nó khai báo được những gì trong đó!
#fuses NOWDT,PUT,HS,NOPROTECT
Thiết lập các config
#use delay(clock=10000000)
Khai báo tần số dao động cấp cho PIC
output_high(PIN_B0)
Xuất ra chân RB0 mức logic 1 (tức 5V), do khi thực hiện hàm này đã bao hàm luôn việc tác động lên thanh ghi TRISB (dùng chọn chân I/O) do vậy ta không cần viết lệnh chọn chân I/O nữa.
output_low(PIN_B0)
Ngược lại
delay_ms(1000)
Tạo trễ khoảng thời gian theo mili giây là 1000 (tức 1s)
Chú ý hàm này chỉ có tác dụng khi có khai báo tần số dao động cấp cho PIC
Và bây giờ thử làm cho tất cả 8 led nối với portB chớp tắt 1s xem nào!Phải chăng ta sẽ làm như sau (Viết trong vòng lặp while):
{
output_high(PIN_B0);
output_high(PIN_B1);
output_high(PIN_B2);
output_high(PIN_B3);
output_high(PIN_B4);
output_high(PIN_B5);
output_high(PIN_B6);
output_high(PIN_B7);
delay_ms(1000);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B3);
output_low(PIN_B4);
output_low(PIN_B5);
output_low(PIN_B6);
output_low(PIN_B7);
delay_ms(1000);
}
Viết như thế này thì quá dài và thiếu chính xác nữa, có cách nào khác hay hơn không ? Sao ta không xuất đẩy hẳn portB lên mức cao,tạo trễ 1s rồi ép cho nó xuống mức thấp,tạo trễ 1s cùng một lúc nhỉ !
Bài tiếp theo sẽ đưa ra câu trả lời....
http://www.freewebtown.com/nhhao/PIC/Delay%201s%20RB0.GIF
Bạn ơi , khi mình compile cái code như trên thì nó báo lỗi warning về thiếu "void" . Mình bỏ thêm : void main(void) vào thì nó mới chạy .
Những function : delay() , rs232(), i2c thì tìm ở đâu vậy ???
thanco112
12-10-2007, 02:43 AM
Oe oe, các bác lừa em nhá. Các bác bảo là tập trung mổ xẻ phần PWM làm em đọc mãi hết hai mấy trang mà thấy có mỗi 2 bài liên quan. Bác nào biết về phần này thì chỉ bảo em với ạ.
Em đang có một con step motor 4 dây (đỏ, xám- đen, vàng). Em đang tìm cách điều khiển nó (chạy, dừng, đảo chiều) nhưng mà chưa biết làm thế nào cả. Các bác cho em hỏi:
1. Em dùng 16f877 điều khiển nó có được không?
2. Cần phải có những kiến thức gì để điều khiển nó?
Bác nào có tài liệu về phần này bằng tiếng Việt thì share cho em với ạ.
Em cám ơn các bác ạ!!!!
Tất nhiên dùng 16F877 được, phí phạm nữa là đằng khác.
Tài liệu tiếng Việt về stepper motor, bạn vào phần điều khiển motor trong diễn đàn này tìm.
Stepper motor của bạn nếu công suất bé có thể dùng ULN lái.
Tham khảo điều khiển stepper motor ở đây:http://www.interq.or.jp/japan/se-inoue/e_step.htm
http://www.interq.or.jp/japan/se-inoue/picture/step1.jpg
Nguoidumuc204
12-10-2007, 09:41 AM
output_high(pin_xx);
output_low (pin_xx);
Hai câu lệnh trên chỉ làm cho chân ra xx là cao hay thấp, ứng với mức logic 1 hoặc 0.trong bài trên ta muốn cho sáng tất một port thì chỉ càn câu lệnh :
void main (void )
{
set_tris_b(0); // cả port B là port ra
set_tris_c(0); // cả port C là port ra
port_b(0x00); // khởi tạo giá trị đầu port B là 0 ( Tất cả led đều tắt )
port_c(0x00); // khởi tạo giá trị đầu port B là 0 ( Tất cả led đều tắt )
delay_ms(100);
while(1)
{
port_b(0xff);
delay_ms(1000);
port_c(0xff);
delay_ms(1000);
}
}
vandungevn
12-10-2007, 06:12 PM
Những function : delay() , rs232(), i2c thì tìm ở đâu vậy ???
bạn xem rõ hơn trong phần help của nó nhé, hoặc tạo new project = PIC Wizard xem trong đó có nói về Những function : delay() , rs232(), i2c ......!
manhckgtcck45
12-10-2007, 10:28 PM
Các anh ơi giúp e với. Các anh có thể chỉ cho em cách sử dụng ngắt ngoài để đếm thời gian của sự thay đổi tín hiệu vào port B không?
thongtr
13-10-2007, 12:13 AM
cá pac ơi giúp em!! em bi lỗi gì vậy!
cá pac ơi giúp em!! em bi lỗi gì vậy!
Bạn không nhận thấy chương trình đòi dấu "}" à?
thongtr
13-10-2007, 12:52 PM
mình cũng a thêm đấu } vào rồi nhưng cũng ko có tác dụng!! với lại mình đưa chuột tới đấu } cuối cùng đó thì nó hiện ra màu xanh và nhìn lên trên thì thấy màu xanh đó ứng với đấu { dưới hàm void main(void) !!!
mình cũng ko biết bị chuyện nữa!!
thongtr
13-10-2007, 02:04 PM
Em vừa mới viết xong ct hiển thị LCD 4 bit! có hiệu ứng chữ chạy rất hay!! em post lên cho các pác tham khảo nhé! và góp ý cho em nhé!
#include <16F877A.h>
#include <DEFS_16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define use_portb_lcd TRUE
#include <lcd.c>
const unsigned char line1[]={'H','E','L','L','O',' ','P','I','C','V','N','!','#'};
const unsigned char line2[]={'Y','H',':','T','H','O','N','G','T','R','0','6', '0','1','@',\
'Y','A','H','O','O','.','C','O','M','#'};
void main(void)
{ while(true)
{
int I=0,y=0,k=0,z=0;
delay_ms(100); // tao tre 100ms cho LCD khoi dong
lcd_init();
lcd_gotoxy(1,1);
while (line1[y]!='#')
{
lcd_putc(line1[y]);
delay_ms(200);
y++;
}
lcd_gotoxy(1,2);
while (i<16)
{
lcd_putc(line2[I]);
i++;
delay_ms(200);
}
i=2;
while (line2[z]!='#')
{
lcd_init();
lcd_gotoxy(1,1);
y=0;
while (line1[y]!='#')
{
lcd_putc(line1[y]);
y++; }
lcd_gotoxy(1,2);
k=i+16;
for(z=i;z<k;z++)
{lcd_putc(line2[z]);}
delay_ms(400);
i++;
}
}
}
Chương trình này minh mô phỏng chạy rồi nhung sao khi cho chạy thực tế khì ko dc!!
Mình đã mắc mạch theo sơ đồ này!! (chỉ có thay thạch anh 20M thôi!)
mình cũng a thêm đấu } vào rồi nhưng cũng ko có tác dụng!! với lại mình đưa chuột tới đấu } cuối cùng đó thì nó hiện ra màu xanh và nhìn lên trên thì thấy màu xanh đó ứng với đấu { dưới hàm void main(void) !!!
mình cũng ko biết bị chuyện nữa!!
- Bạn thiếu dấu ngoặc kép của line1[].
- Chưa include file lcd.c
- Chú ý phép gán = và phép so sánh bằng ==
Việc chạy mô phỏng đúng ko hẳn thực tế sẽ đúng nhưng chạy mô phỏng sai thì chạy trên mạch thật sai là cái chắc.
ghosttn
13-10-2007, 05:21 PM
Em muon' cho 595 ra 8 bit 1 luc nhung lam mai khong duoc. Em sai ởi chỗ nào
do mới học em chỉ có thể nghĩ đơực như vậy thôi. các anh tối ưu code+ mạch hộ em với.
====================================
#include <16f877a.h>
#use delay(clock=4M)
int8 i;
void input_byte(){
for(i=0;i<=7;i++){
output_bit(pin_B0,0); //1.tao xung cho pin_sck
output_bit(pin_B1,i%=2);//2.dich du lieu vao luc pin_sck o trang thai suon
output_bit(pin_B0,1); //3.ket thuc xung tai pin_sck
}
}
void output_byte(){
output_bit(pin_B2,0); //1.tao xung clock cho pin_rck
delay_ms(100); //2.dung lai de xem
output_bit(pin_B2,1); //3.ket thuc xung tai pin_rck
}
void main(){
set_tris_b(0);
output_bit(pin_B4,0);//khoi dong 595 pin_/OE
while(1){
output_bit(pin_B3,1);//cho phep ghi du lieu pin_MR =1
input_byte();
output_byte();
output_bit(pin_B3,0);//all pin out 595= level low
}//end while
}// end main
==========================
thanco112
14-10-2007, 01:12 AM
Các bác cho em hỏi về các loại ngắt của con 16f877 này với ạ. Tên của nó này, chế độ hoạt động của nó như thế nào (khi nào thì ngắt ấy ạ). Em gà, mới nghiên cứu pic, các bác giúp cho!
GLOBAL
INT_RTCC
INT_RB
INT_EXT
INT_AD
INT_TBE
INT_RDA
INT_TIMER1
INT_TIMER2
INT_CCP1
INT_CCP2
INT_SSP
INT_PSP
INT_BUSCOL
INT_EEPROM
INT_TIMER0
Thanks các bác nhiều
vandungevn
22-10-2007, 02:45 PM
Dưới đây là một chương trình đưa một byte bằng 74hc595 dùng trên CCS
void display(unsigned char dataout)
{
unsigned char temp;
//dataout = 0xa4;
output_low(pin_c0);
for(i=0;i<8;i++)
{
temp = dataout;
temp = temp&0x80;
if(temp==0x80)
{
output_high(pin_c1); // Data
}
else
{
output_low(pin_c1); // Data
}
output_high(pin_c0); // Clock
dataout *=2;
output_low(pin_c0); // Clock
}
output_high(pin_c2); // Latch
output_low(pin_c2); // Latch
}
chúc bạn thành công.!
Yeu PIC
26-10-2007, 07:06 PM
trong ct mình dùng hai file của bộ compiler: lcd.c và ds1307.c
khi biên dịch thành file .hex thì bị những lỗi về delay như thế này:
Nguyên nhân do đau vậy!
ngoctuan
26-10-2007, 10:09 PM
chào các Bác, Em là thành viên mới , rất mong được chào đón. mong các bác chỉ cho Em về cuonter (Em đang làm đề tài mạch đếm sản phẩm ma chưa hiểu gì về cuonter) mong các bác chỉ dùm em .cám ơn các bác nhiều!
toanck86
03-11-2007, 05:14 PM
em cũng muốn hỏi về counter, và cho hỏi đếm xung encoder bằng counter có được không nhỉ, bác nào làm về phần này cho em xin code & đề tài với
tungtot_vl
19-11-2007, 03:25 PM
bác nào rành về timer cho em hỏi tí
em thấy các bài timer khi chương trình đã nhảy vào làm việc trong timer thì nó thực hiện lập đi lập lại trong timer mà không thoát ra ngoài. thế nếu em muốn thoát ra khỏi timer để thực hiện các lệnh khác ở ngoài vòng lập while thì làm thế nào hả các bác.
ý em muốn dùng timer như ngắt ngoài vậy các bác ạ. sau khi thực hiện ngắt xong thì thoát ra để thực hiện lệnh kế tiếp.
LeDuc
20-11-2007, 03:45 AM
Giúp em với ... em cần tiết kiệm chân của con Pic 887 , nên em muốn dùng cổng nối tiếp để truyền dữ liệu cho con 74LS164 qua 2 chân C6 va C7 của cổng nối tiếp quét 4 con led 7 đoạn , em viết mãi mà không được , mong các anh giúp đỡ .
đây là đoạn code em viết để quét 4 led 7 đoạn qua port D cua con pic ...Mong các anh sửa lại để có thể truyền dữ liệu qua 2 chân C6 va C7 giúp em ..
CODE :
/
#include <16f887.h>
#include <luutinh.h>
int8 i,a,b,k=0;
int8 so[4],led[]={0,1,2,3,4,5,6,7,8,9},quet[]={128,64,32,16};
#int_rtcc
void quetled()
{
set_timer0(99);b=a;
so[0]=a%10;a/=10;
so[1]=a%10;a/=10;
so[2]=a%10;a/=10;
so[3]=a; a=b;
portD=(led[so[k]]+quet[k]);
k++;
if(k==4)k=0;
}
void xet_nhiet_do()
/*..................*/
void main()
{
setup_timer_0(rtcc_internal|rtcc_div_128)
set_timer0(99);
setup_adc(adc_clock_internal);
setup_adc_ports(all_analog);
enable_interrupts(int_rctt);
enable_interrupts(global):
trisa=255;
trisb=trisc=trisd=0;
while(true)
{
if(xet_nhiet_do>31) che_do(1);
//................................
}
nếu sử dụng cách quét led qua 1 con giai mã 7447 thi phải tốn đến 8 chân pic ở port D , em muốn sử dụng thanh ghi dịch 74ls164 để quét led qua 2 cổng nối tiếp .Nhưng kô biết trong CCS qui đinh code như thế nào cả . Rất mong các anh giúp đỡ ...
tungtot_vl
21-11-2007, 10:06 AM
dùng ngắt trên các chân từ rc4 -> rc7 khi chạy thì báo lỗi invalid pri_processor diẻctive.
em thấy trong các ngắt có loại ngắt này nhưng khi khai báo sao nó không hiểu nhỉ.
#include<16f877a.h>
#fuses NOLVP,NOWDT,PUT,hs,NOPROTECT
#device 16F877*=16 ADC=8
#use delay(clock=20000000)
#use fast_io(a)
#byte porta=0x05
#use fast_io(b)
#byte portb=0x06
#use fast_io(c)
#byte portc=0x07
#use fast_io(d)
#byte portd=0x08
#use fast_io(e)
#byte porte=0x09
#bit ra0 = porta.0
#bit ra1 = porta.1
#bit ra2 = porta.2
#bit rc3 = portc.3
//================================================== ====
int u,t;
int16 count;
#INT_RC
void interrupt_RC()
{ int8 i,l,x,y;
portb =0;
for(i=0;i<24;i++)
{
portb = 0xff;
delay_ms(1000);
portb = 0;
delay_ms(1000);
}
}
//================================================== ===
void main()
{
set_tris_b(0);
set_tris_a(0);
set_tris_c(0xff);
set_tris_e(0);
set_tris_d(0);
enable_interrupts(global);
enable_interrupts(int_RC);
ext_int_edge(h_TO_l);
// rc3 = 0;
while(true)
{
}
}
//=============================================
namqn
21-11-2007, 05:49 PM
dùng ngắt trên các chân từ rc4 -> rc7 khi chạy thì báo lỗi invalid pri_processor diẻctive.
em thấy trong các ngắt có loại ngắt này nhưng khi khai báo sao nó không hiểu nhỉ.
...
Tôi không hề thấy có ngắt trên các chân RC4 đến RC7 trong datasheet của PIC16F877A, mà chỉ thấy có ngắt trên các chân RB4 đến RB7 (port change interrupt). Bạn thấy ngắt trên các chân RC4 đến RC7 ở đâu, có thể cho chúng tôi biết được không?
Thân,
toanck86
21-11-2007, 09:13 PM
Bác nào làm về counter rồi cho em ví dụ với. Sao khi khai báo cho timer0 ở chế độ counter rồi cho xung vào chân RA4 thì không thấy gì xảy ra nhỉ:(
namqn
21-11-2007, 10:03 PM
Bác nào làm về counter rồi cho em ví dụ với. Sao khi khai báo cho timer0 ở chế độ counter rồi cho xung vào chân RA4 thì không thấy gì xảy ra nhỉ:(
Bạn muốn chuyện gì sẽ xảy ra? Bạn đã viết code để xử lý nó chưa? Lý do gì khiến bạn cho rằng không có chuyện gì xảy ra?
Thân,
Mr.Bi
01-12-2007, 12:57 AM
#include <16F877A.h>
#include <DEFINE_16F877A.h>
#include <DEFINE_16F87x.h>
#fuses NOWDT,XT,NOPROTECT,NOLVP,PUT
#use delay(clock=4000000)
#use standard_io (B)
#use standard_io (A)
#define E PIN_D0
#define RS PIN_D1
#define RW PIN_D2
#define LCD_D4 PIN_D4
#define LCD_D5 PIN_D5
#define LCD_D6 PIN_D6
#define LCD_D7 PIN_D7
#bit CANCEL =0x05.1 // CANCEL = RA1
#bit OK =0x05.0 // OK = RA0
unsigned int8 key[] ; // mang luu cac so da nhap tu ban phim
const unsigned int8 num[11] = {'0','1','2','3','4','5','6','7','8','9'} ;
const unsigned int8 num_ss[11] = {' ','3','9','5','2','6','1','0'} ; // cac so dung de so sanh
unsigned int8 a = 0 ; // bien dem cac so nhap tu ban phim
unsigned int8 b = 0 ; // bien dem so lan sai ma
void LCD_Init ( void ); // ham khoi tao LCD
void LCD_SetPosition ( unsigned int data );//Thiet lap vi tri con tro
void LCD_PutChar ( unsigned int data ); // Ham viet1kitu/1chuoi len LCD
void LCD_PutCmd ( unsigned int data ) ; // Ham gui lenh len LCD
void tao_xung_E(); // Xung kich hoat
void send_to_LCD( unsigned int data); // Dat du lieu len chan Data
void delay_ms_INT(unsigned long i)
{ unsigned long k , j ;
for(k=0;k<=i;k++) { for(j=0;j<=i;j++){;} }
}
void LCD_Init ( void )
{
delay_ms(200); // thoi gian de LCD khoi dong
output_low(RW); // RW = 0
output_low(RS); // che do gui lenh
send_to_LCD( 0x00 );
output_high ( E ); output_low ( E ); delay_ms ( 10 );
send_to_LCD( 0x03 ); /* init with specific nibbles to start 4-bit mode */
output_high ( E ); output_low ( E ); delay_ms ( 3 ); // tao xung tren chan E
output_high ( E ); output_low ( E ); delay_ms ( 3 );
output_high ( E ); output_low ( E ); delay_ms ( 3 );
send_to_LCD( 0x02 ); /* set 4-bit interface */
output_high ( E ); output_low ( E ); delay_ms ( 3 ); // tao xung tren chan E
LCD_PutCmd ( 0x2C ); /* function set (all lines, 5x7 characters) */
LCD_PutCmd ( 0x0C); /* display ON, cursor off, no blink */
LCD_PutCmd ( 0x06 ); /* entry mode set, increment & scroll left */
LCD_PutCmd ( 0x01 ); /* clear display */
}
void LCD_SetPosition ( unsigned int data )
{
send_to_LCD( swap ( data ) | 0x08 );
output_high ( E ); output_low ( E ); delay_ms ( 3 ); // tao xung tren chan E
send_to_LCD( swap ( data ) );
output_high ( E ); output_low ( E ); delay_ms ( 3 ); // tao xung tren chan E
}
void LCD_PutChar ( unsigned int data )
{
output_high( RS ); //RS = 1
output_low ( RW ); //RW = 0
send_to_LCD( swap ( data ) ); // gui 4 bit cao
output_high ( E ); output_low ( E ); delay_ms ( 3 ); // tao xung tren chan E
send_to_LCD( swap ( data ) ); //gui 4 bit thap
output_high ( E ); output_low ( E ); delay_ms ( 3 ); // tao xung tren chan E
}
void LCD_PutCmd ( unsigned int data )
{
output_low(RS); // RS = 0
output_low(RW); // RW = 0
send_to_LCD( swap(data) ); // gui 4 bit cao
output_high (E); output_low (E); delay_ms (3);
send_to_LCD( swap(data) ); // gui 4 bit thap
output_high (E); output_low (E); delay_ms ( 3 );
}
void send_to_LCD( unsigned int data )
{
output_bit ( LCD_D4, data & 0x01 );
output_bit ( LCD_D5, data & 0x02 );
output_bit ( LCD_D6, data & 0x04 );
output_bit ( LCD_D7, data & 0x08 );
}
void quetphim_hienthi()
{ PORTB = 0b111111110 ; if (RB4==0) { delay_ms_INT(50);
while(RB4==0) continue ;
delay_ms_INT(20);
LCD_PutChar('0') ; key[a++] = num[0];
} ;
if (RB5==0) { delay_ms_INT(50);
while(RB5==0) continue ;
delay_ms_INT(20);
LCD_PutChar('3') ; key[a++] = num[3];
} ;
if (RB6==0) { delay_ms_INT(50);
while(RB6==0) continue ;
delay_ms_INT(20);
LCD_PutChar('6') ; key[a++] = num[6];
} ;
if (RB7==0) { delay_ms_INT(50);
while(RB7==0) continue ;
delay_ms_INT(20);
LCD_PutChar('9') ; key[a++] = num[9];
} ;
PORTB = 0b111111101 ; if (RB4==0) { delay_ms_INT(50);
while(RB4==0) continue ;
delay_ms_INT(20);
LCD_PutChar('1') ; key[a++] = num[1];
} ;
if (RB5==0) { delay_ms_INT(50);
while(RB5==0) continue ;
delay_ms_INT(20);
LCD_PutChar('4') ; key[a++] = num[4];
} ;
if (RB6==0) { delay_ms_INT(50);
while(RB6==0) continue ;
delay_ms_INT(20);
LCD_PutChar('7') ; key[a++] = num[7];
} ;
PORTB = 0b111111011 ; if (RB4==0) { delay_ms_INT(50);
while(RB4==0) continue ;
delay_ms_INT(20);
LCD_PutChar('2') ; key[a++] = num[2];
} ;
if (RB5==0) { delay_ms_INT(50);
while(RB5==0) continue ;
delay_ms_INT(20);
LCD_PutChar('5') ; key[a++] = num[5];
} ;
if (RB6==0) { delay_ms_INT(50);
while(RB6==0) continue ;
delay_ms_INT(20);
LCD_PutChar('8') ; key[a++] = num[8];
} ;
}
#int_RB
void ngat_RB(void)
{ LCD_PutCmd(0x83); // dong1 cot 5
while (OK && CANCEL) quetphim_hienthi(); // nut OK chua dc nhan
if(CANCEL==0) {delay_ms_INT(20); // nhan OK
while(CANCEL==0) continue ;
delay_ms_INT(20);
goto THOAT ; };
if(OK==0 ) {delay_ms_INT(20); // nhan OK
while(OK==0) continue ;
delay_ms_INT(20);
if (a==7)
{
if(key[1]!=num_ss[1]) {goto HERE ;};
if(key[2]!=num_ss[2]) {goto HERE ;};
if(key[3]!=num_ss[3]) {goto HERE ;};
if(key[4]!=num_ss[4]) {goto HERE ;};
if(key[5]!=num_ss[5]) {goto HERE ;};
if(key[6]!=num_ss[6]) {goto HERE ;};
if(key[7]!=num_ss[7]) {goto HERE ;};
LCD_PutCmd(0x01);
LCD_PutCmd(0x84);
LCD_PutChar('Y') ;
LCD_PutChar('E') ;
LCD_PutChar('S') ;
delay_ms(2000) ;
HERE :
LCD_PutCmd(0x01);
LCD_PutCmd(0x84);
LCD_PutChar('W') ;
LCD_PutChar('r') ;
LCD_PutChar('o') ;
LCD_PutChar('n') ;
LCD_PutChar('g') ;
LCD_PutChar('!') ;
b++; // dem so lan sai ma
} ;
if (a!=7){ LCD_PutCmd(0x01);
LCD_PutCmd(0x84);
LCD_PutChar('W') ;
LCD_PutChar('r') ;
LCD_PutChar('o') ;
LCD_PutChar('n') ;
LCD_PutChar('g') ;
LCD_PutChar('!') ;
b++; // dem so lan sai ma
delay_ms(2000) ;
} ;
} ;
THOAT :
LCD_PutCmd(0x01);
LCD_PutCmd(0xC4);
LCD_PutChar('R') ;
LCD_PutChar('e') ;
LCD_PutChar('a') ;
LCD_PutChar('d') ;
LCD_PutChar('y') ;
LCD_PutChar('!') ;
RBIF = 0 ;
}
void main()
{ set_tris_A(0xFF); PORTA = 0xFF ;
set_tris_B(0xF0); PORTB = 0xF0 ;
set_tris_C(0x00); PORTC = 0;
set_tris_D(0x00);
LCD_Init(); // khoi tao LCD
enable_interrupts(global);
enable_interrupts(int_RB);
ext_int_edge(H_to_L);
LCD_PutCmd(0xC4);
LCD_PutChar('R') ;
LCD_PutChar('e') ;
LCD_PutChar('a') ;
LCD_PutChar('d') ;
LCD_PutChar('y') ;
LCD_PutChar('!') ;
while(1) ;
}
cho em hỏi chút xíu !
- em khai báo biến đếm a toàn cục , như trên code
- ý định của em : mỗi lần nhấn phím thì mảng key[] sẽ tự nạp số vào & nạp theo thứ tự , vì vậy , sau mỗi lần nhấn phím , em cho key[a++]
- nhưng ko hiểu sao , cứ mỗi lần nhấn đúng mã số "3952610", thì ct cứ nhảy tới label HERE .. em nghi ngờ ngay chỗ so sánh mảng key[] và num_ss[] ;
- chắc chắn key[] có giá trị ko đúng như các số mình đã nhấn !
các anh thấy em phân tích vậy có đúng ko ?
- thứ nữa : sau mỗi lần chạy hết ct ngắt thì ko bit ct có thoát khỏi ngắt hay ko ? nhưng em nhấn phím trở lại thì LCD ko chịu hiện số nữa , chỉ khi nhấn từ 3 lần trở lên thì số mới hiện trở lại . LCD lúc ấy đang bận ? nhưng nó có làm gì đâu . Đến nhãn THOAT , chỉ việc hiện " Ready!" lên thui mà . Có lẽ tới chỗ này ct bị treo !?
Mr.Bi
03-12-2007, 12:09 AM
uhm ! rùi .. cuối cùng mình cũng tìm ra lỗi .
- Đúng là ngay chỗ so sánh key[] & num_ss[] ấy !
phải là :
if (key[0] != num_ss[1]) { goto HERE1 ; ) ;
if (key[1] != num_ss[2]) { goto HERE1 ; ) ;
.....
vì sao vậy ? mình đã bit ..nhưng có lẽ để các bạn mắc phải lỗi ngớ ngẩn như mình & tìm ra lời giải thì sẽ nhớ lâu hơn !
Còn cái chỗ : sau khi hết ct ngắt ,ct vẫn ko chịu thoát ra ngoài main() & đứng đợi while(1) ; cụ thể là khi bấm nút .. LCD vẫn ko hiển thị.. sau 3 lần nhấn só mới bắt đầu hiển thị --> mình vẫn chưa tìm đc nguyên nhân .! sẽ cố gắng chữa lỗi tiếp
các bác chỉ em cách tính step size với.
thongtr
30-12-2007, 10:02 AM
các pác chỉ cho mình với! mình đang làm với con lm335 nhưng sao nhiệt độ của nó không có ổn định tới chênh lệch nhau tới 4 độ. các bác có cách gì chỉ cho mình với! mình đang dùng con 16F877a
Sangcao
31-12-2007, 12:55 PM
lm35 để đo nhiệt độ cho vui thôi.phụ thuộc vào nhiều vấn đề, ko chỉ là do con lm35, AD của PIC, thuât toán của bạn.Bọn TQ nó thường dùng thuật toán tra bảng. nếu cần chính xác, ổn định thì bạn nên lhệ bác Cường Quay , mình ko nhớ là con gì, giá khoảng 40$ thì phải. bảo đảm ok luôn!
bean984
02-01-2008, 10:28 AM
các bác cho em hỏi: làm thế nào để biết con slave đã nhận xong chuỗi ký tự? e dùng rs232 để truyền nhận giữa 2 con pic.
em cũng thử dùng hàm itoa để chuyển số int sang chuỗi và dùng hàm printf để truyền.
bên nhận em dùng hàm atol để chuyển chuỗi về dạng int16 rồi hiể thị. nhưng kết quả hiển thị lại không chính xác. cụ thể là sau chuỗi số là các ký tự lạ.
bác nào đã làm vấn đề này rồi xin chỉ giáo giúp em.
nếu có code thì tốt quá
picthanh
08-01-2008, 11:46 PM
các bác cho em hỏi trong CCS mình muốn cộng các ký tự riêng lẻ thành một chuỗi ký tự thì dùng lệnh gì? bài toán của em cụ thể như sau:dùng ma trận phím 4x3 để nhập các ký tự từ 0-9 sau đó cộng các ký tự này lại thành một chuỗi.Sau đó hiển thị chuỗi này lên LCD nhưng em làm hoài mà nó cũng không chạy, khi dịch chương trình thì cũng không thấy báo lỗi gì cả.Em đã thử cho hiện từng ký tự thì chương trình chạy rất ok! nhưng khi cộng các ký tự lai bằng lệnh "key=key+k;" thi ko chạy được.
em dùng con 16F877A ,thạch anh 20MHz
#include "D:\PIC PROGRAM\dk.h"
#include <KBD.C>
#include <lcd.c>
char k,*key;
void main()
{
port_b_pullups(TRUE);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
kbd_init();
lcd_init();
lcd_putc('\f');
key=0;
while(1)
{
k=0;
k=kbd_getc();
key=key+k; //lenh nay hinh nhu sai
if(k!=0)
{
lcd_gotoxy(1,1);
lcd_putc(key);
}
}
}
mong các cao thủ ra tay giúp đỡ !
namqn
08-01-2008, 11:51 PM
Bạn tự nêu cách giải quyết rồi đó. Dùng một biến chuỗi để lưu chuỗi kết quả, mỗi lần thêm vào chuỗi thì dùng hàm nối chuỗi để nối chuỗi đã có và ký tự cần thêm. Bạn xem tài liệu hướng dẫn của CCS C về các hàm này.
Thân,
picthanh
09-01-2008, 01:59 PM
với cách viết mà em post ở bài trước thì nó chỉ hiện được phím đầu tiên mà mình nhấn thôi,còn các phím sau đó thì LCD chỉ hiện lên các ký tự lạ thôi.
Còn hàm nối chuỗi mà Bác nói là hàm nào ,có phải là hàm "srcat(key,string1);"này ko?
em cũng thử rồi nhưng ko được nên phải cầu cứu các Bác nè.
#include "D:\PIC PROGRAM\dk.h"
#include <KBD.C>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lcd.c>
char string1[10];
char i,t, keyscan;
char k,key[10];
void main()
{
port_b_pullups(TRUE);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
kbd_init();
lcd_init();
SET_TRIS_C( 0x00 );
output_bit(PIN_C4, 1);output_bit(PIN_C5, 1);
delay_ms(1000);
output_bit(PIN_C4, 0);output_bit(PIN_C5, 0);
i=0;
lcd_putc('\f');
while(1)
{
k = kbd_getc();
if (k!=0)
{
strcpy(string1,k);
strcat(key,string1);
for(i=0;i<strlen(key);i++)
lcd_putc(key[i]);
}
}
}
với chương trình này thì LCD hiện những ký tự lạ có cả tiếng Nhật nửa.nói chung là nó ko chạy đúng theo những gì mà em cần
có Bác nào đã làm cái này chưa chỉ em với.
namqn
09-01-2008, 08:07 PM
Tôi không rõ CCS C sẽ xử lý thế nào khi bạn dùng lệnh k = kbd_getc();. Vì bạn đã khai báo k là một mảng ký tự (tối đa 10 ký tự), trong khi prototype của kbd_getc() lại cho thấy giá trị trả về là 1 ký tự. Bạn thử lại với lệnh sau xem sao:
k[0] = kbd_getc();
Đúng là tôi đã đề cập đến hàm strcat(). Cần biết là tôi không sử dụng CCS C, chỉ đọc tài liệu hướng dẫn của phần mềm để giúp bạn. Do đó, bạn sẽ là người thử nghiệm các giải pháp mà tôi cho là sẽ giúp ích cho bạn.
Thân,
nod32
10-01-2008, 12:37 AM
Tôi đang học CCS chưa biết sử dụng nhiều Huynh có thể post thêm bai hướng dẫn hay tài liệu được không?
picthanh
10-01-2008, 01:04 AM
Bác "nampn" oi!em khai báo "k" là biến kiểu char bình thường mà, còn biến "key" mới là biến kiểu mảng "char k,key[10]". em sẽ thử cách này của Bác thử xem sao. Cảm ơn Bác rất nhiều.
namqn
10-01-2008, 01:21 AM
Bác "nampn" oi!em khai báo "k" là biến kiểu char bình thường mà, còn biến "key" mới là biến kiểu mảng "char k,key[10]". em sẽ thử cách này của Bác thử xem sao. Cảm ơn Bác rất nhiều.
Vâng, tôi nhầm, bạn đã khai báo k là char. Nhưng khi đó hàm strcpy() lại có khả năng chạy sai, vì nó cần 2 đối số kiểu string.
Thân,
bean984
14-01-2008, 11:47 AM
giúp mình với!!!!!!
mình cũng đang gặp phải lỗi này. chương trình của mình sử dụng ngắt RB và timer0. hàm phục vụ ngắt RB của mình có gọi đến khá nhiều hàm con. khi mình bỏ hẳn hàm phục vụ ngắt RB ra khỏi ct thì hoạt động của timer0 là đúng. còn khi mình thêm vào hàm phục vụ ngắt RB,mặc dù ngắt RB không hề sảy ra nhưng timer0 của mình vẫn chạy không chính xác.
cho mình hỏi bạn khangcodt đã khắc phục được lỗi timer chạy sai khi trong hàm phục vụ ngắt gọi đến các hàm con khác chưa vậy?
mình cảm ơn nha.
bean984
14-01-2008, 01:55 PM
cho mình hỏi thêm câu nữa nhé.
mình dùng hàm printf(); để truyền dl qua máy tính.
1) làm thế nào để biết pic đã truyền xong mảng ký tự
2) để truyền một số nguyên mình đã thực hiện như sau:
itoa(trunggian2,10,s);//chuyển số nguyên thành mảng ký tự
printf(s);
trong đó biến trunggian2 là int16, s là mảng char. nhưng khi mình thử test với hyper terminal thì kết quả nhận được lại không đúng. cụ thể là sau những số nhận được lại có thêm các ký tự lạ.
bạn nào đã làm về vấn đề này rồi xin chỉ giúp mình với
mình cảm ơn nhiều.
bean984
15-01-2008, 02:02 PM
cho mình hỏi :
khi truyền một mảng char từ pic lên máy tính thì ngắt RDA sảy ra sau khi truyền xong cả mảng hay cứ mỗi lần truyền xong một phần tử thì xảy ra ngắt RDA?
mình cảm ơn!
namqn
15-01-2008, 08:17 PM
cho mình hỏi :
khi truyền một mảng char từ pic lên máy tính thì ngắt RDA sảy ra sau khi truyền xong cả mảng hay cứ mỗi lần truyền xong một phần tử thì xảy ra ngắt RDA?
mình cảm ơn!
Ngắt INT_RDA xảy ra khi PIC nhận được dữ liệu tại cổng USART của nó (ví dụ do máy tính truyền đến), còn ngắt INT_TBE xảy ra khi PIC truyền dữ liệu qua cổng USART của nó (ví dụ truyền đến máy tính). Câu hỏi của bạn thuộc loại 'râu ông nọ cắm cằm bà kia'.
Ngắt INT_RDA xảy ra mỗi khi PIC16F877A nhận được 1 ký tự ở bộ đệm nhận, người dùng nên nhanh chóng đọc dữ liệu từ bộ đệm để PIC có thể ghi ký tự kế tiếp ngay khi thanh ghi dịch đã có đủ dữ liệu.
Thân,
bean984
16-01-2008, 08:56 AM
em cảm ơn anh namqn nhiều.
cho em hỏi thêm câu này nữa nhé
em dùng con 16f877a để nhận mảng ký tự truyền từ môt con 16f877a khác. mảng ký tự kết thúc bằng ký tự @.
bên phát:
itoa(x,10,s);// s khai báo là char s[5]
s[4]='@';// vì e k biết s kết thúc bằng ký tự gì
printf(s);
bên thu em thực hiện truyền vài lần(thay đổi giá trị của x bằng cách ấn nút) thì e chỉ nhận được lần đầu tiên. truyền các lần tiếp theo thì nó bị đơ luôn, không chạy nữa. e chạy mô phỏng bằng proteus.
đây là code bên phía nhận
#INT_RDA
RECEIVER()
{
char kt;
int i;
char s1[4];
i=0;
kt=fgetc(pc);
while(kt!='@')
{
s1[i]=kt;
i++;
kt=fgetc(pc);
}
lcd_clear();
delay_ms(1);
lcd_display_str(0, 0, s1);
}
bean984
16-01-2008, 03:17 PM
cho mình hỏi một câu nữa
khi ngắt RDA xảy ra thì cờ nào được set lên 1, và khi kết thúc ngăt nó có tự động xóa bít đó không?
bien_van_khat
16-01-2008, 06:04 PM
cho mình hỏi một câu nữa
khi ngắt RDA xảy ra thì cờ nào được set lên 1, và khi kết thúc ngăt nó có tự động xóa bít đó không?
Ngắt RDA xảy ra khi cờ RCIF trong thanh ghi PIR1 được set, bạn có thể coi giản đồ thời gian trong datasheet trang 120.
em cảm ơn anh namqn nhiều.
cho em hỏi thêm câu này nữa nhé
em dùng con 16f877a để nhận mảng ký tự truyền từ môt con 16f877a khác. mảng ký tự kết thúc bằng ký tự @.
bên phát:
itoa(x,10,s);// s khai báo là char s[5]
s[4]='@';// vì e k biết s kết thúc bằng ký tự gì
printf(s);
Bạn xem lại mẫu hàm của hàm printf, muốn gửi 1 chuỗi bạn phải gọi như sau
printf("%s", s);
bean984
18-01-2008, 02:22 PM
cho mình hỏi cái này nhé
nếu dùng lệnh printf("%s", s); thì ký tự kết thúc của chuỗi s là gì?
mình định dùng ký tự này để xử lý việc nhận chuỗi s. có phải ký null không nhỉ?
nguyendinhtuan
18-01-2008, 11:47 PM
các chương trình ví dụ
bien_van_khat
18-01-2008, 11:55 PM
cho mình hỏi cái này nhé
nếu dùng lệnh printf("%s", s); thì ký tự kết thúc của chuỗi s là gì?
mình định dùng ký tự này để xử lý việc nhận chuỗi s. có phải ký null không nhỉ?
Với C, một chuỗi luôn phải kết thúc với ký tự NULL.
bean984
21-01-2008, 09:40 AM
giúp mình cái hàm nhận xâu ký tự
bên phát mình thực hiện như sau:
itoa(x,10,s);//chuyển số nguyên x thành xâu ký tự
printf("%s", s);
còn bên nhận mình thực hiện kiểm tra kt null như sau:
#INT_RDA
RECEIVER()
{
char kt;
int i;
char s1[4];
i=0;
kt=fgetc(pc);
while(kt!=null)
{
s1[i]=kt;
i++;
kt=fgetc(pc);
}
lcd_clear();
delay_ms(1);
lcd_display_str(0, 0, s1);//hiển thị xâu
}
nhưng không thu dc gì. mình k biết lỗi ở đâu nữa
mình cảm ơn.
bien_van_khat
21-01-2008, 10:24 AM
Theo như đoạn code trên, hàm lcd_display_str nhận đối số là một chuỗi do đó chắc chắn nó yêu cầu chuỗi của bạn phải kết thúc = ký tự NULL, chuỗi s1 như trên chưa có ký tự kết thúc.
Bạn nên post cả code của phần phát
bean984
21-01-2008, 02:30 PM
bên phát mình chỉ có hai dòng lệnh vậy thôi vì mình ghép nó vào một chương trình con khác.
void tonghop_so()
{
char s[5];
t1=nghin*10+tram;
t2=chuc*10+donvi;
trunggian2=t1*100+t2;
if((hor==0)&(trunggian2<=5000))
{
rnominal0=trunggian2;
itoa(trunggian2,10,s);//chuyển số nguyên trunggian2 thành xâu ký tự
printf("%s", s);
}
}
khi gọi đến hàm tonghop_so(); thì đồng thời gửi chuỗi.
hàm lcd_display_str(); là hàm hiển thị một mảng ký tự.
void lcd_display_str(int line, int8 posc, char str[])
{
int8 i,j;
j=strlen(str);// Cho xau la co dinh
for (i = posc; i < j+posc ; i++)
{
lcd_display_char(line, i, str[i-posc]);
delay_ms(1);
}
}
tinhgiac_vp
23-02-2008, 07:12 PM
INTERRUPT
Các lệnh dùng cho ngắt:
enable_interrupts(level); //cho phép ngắt kiểu level
disable_interrupts(level); //cấm ngắt kiểu level
ext_int_edge(edge); // chọn cách lấy xung loại edge
level bao gồm:
GLOBAL : ngắt toàn cục
INT_RTCC : tràn TMR0
INT_RB : có thay đổi trạng thái một trong các chân RB4 đến RB7
INT_EXT : ngắt ngoài
INT_AD : chuyển đổi AD đã hoàn tất
INT_TBE : bộ đệm chuyển RS232 trống
INT_RDA : data nhận từ RS232 sẵn sàng
INT_TIMER1 : tràn TMR1
INT_TIMER2 : tràn TMR2
INT_CCP1 : có capture hay compare trên CCP1
INT_CCP2 : có capture hay compare trên CCP2
INT_SSP : có hoạt động SPI hay I2C
INT_PSP : có data vào cổng parallel slave
INT_BUSCOL : xung đột bus
INT_EEPROM : ghi vào eeprom hoàn tất
INT_TIMER0 : tràn TMR0
INT_COMP : kiểm tra bằng nhau comparator
edge bao gồm:
L_TO_H : cạnh lên
H_TO_L : cạnh xuống
Sau khai báo trên để vào đoạn chương trình ngắt, khai báo:
#INT_.........
Ví dụ vào thực thi ngắt ngoài, ta có đoạn code:
#INT_EXT
void ngat_ngoai()
{
//Chương trình ngắt tại đây
}
các cao thủ vui lòng viết 1 ví dụ cụ thể về ngắt ngoài được không??????? Em đã thử viết nhưng không chạy được. Chương trình của em dùng ngắt ngoài RB_0 và hiển thị lên port_C
#include <16F877A.h>
#byte portb = 0x06
#byte portc = 0x07
#use delay (clock = 20000000)
int count=1;
#INT_EXT
void EXT_LED()
{
portc=count;
count=count+1;
delay_us(100);
bit_clear(portb,0);
}
void main() {
ext_int_edge(L_TO_H);
enable_interrupts(INT_EXT);
enable_interrupts(global);
set_tris_b(0xff);
set_tris_c(0x00);
portc=0;
bit_set(portb,0);
while(1)
{
}
}
tinhgiac_vp
23-02-2008, 07:21 PM
Bác F co CCS 4.038 không post lên cho mọi người nữa. Không biết nó có gì mới+tốt hơn không?
anhvietqx
26-02-2008, 11:59 AM
cám ơn các bạn rất nhiều
bean984
03-03-2008, 02:10 PM
giúp mình về cái timer với!!
trong chương trình của mình có sử dụng cả timer và ngắt. Đây là hàm phục vụ ngắt của mình:
#int_RB
void ngat_RB()
{
if((RBIF)&&(RBIE))
{
//if(khoidong0==1)
// goto Thoat;
output_low(pin_A3);
output_low(pin_A4);
output_low(pin_A5);
if(!RB4)
{
if(ver==0)
{
ver=1;
hienthicot1();
goto Thoat;
}
if(ver==1)
{
ver=2;
CPHT=1;
goto Thoat;
}
if(ver==2)
{
ver=3;
doctrunggian2();
hienthicot3();
goto Thoat;
}
if(ver==3)
{
ver=4;
phantich_so(trunggian2);
trunggian=nghin;
lcd_display_blink(0,13);
goto thoat;
}
if(ver==4)
{
ver=5;
trunggian=tram;
if(hor==6)
lcd_display_char(0,13,pw[0]);
lcd_display_blink(0,14);
goto thoat;
}
if(ver==5)
{
trunggian=chuc;
if(hor==6)
lcd_display_char(0,14,pw[0]);
ver=6;
lcd_display_blink(0,15);
goto thoat;
}
if(ver==6)
{
trunggian=donvi;
if(hor==6)
lcd_display_char(0,15,pw[0]);
ver=7;
lcd_display_blink(0,16);
goto thoat;
}
if(ver==7)
{
ver=4;
trunggian=nghin;
if(hor==6)
lcd_display_char(0,16,pw[0]);
lcd_display_blink(0,13);
goto thoat;
}
} // Xong RB4
if(!RB5)
{
if((ver==0)||(ver==1))
goto Thoat;
if(ver==2)
{
ver=1;
hienthicot1();
CPHT=0;
hor=0;
goto Thoat;
}// endif(ver==1)
if(ver==3)
{
if((hor==1)||(hor==2)||(hor==3)||(hor==4)||(hor==5 ))
hor=1;
if((hor==6)||(hor==7)||(hor==8)||(hor==9))
hor=6;
hienthicot2();
ver=2;
goto Thoat;
}// endif(ver==1)
if((ver==4)||(ver==5)||(ver==6)||(ver==7))
{
//RBIF=0;
tonghop_so();
}
}// Endif(RB5)
if(!RB6) // Xu ly tang gia tri
{
if((ver==4)||(ver==5)||(ver==6)||(ver==7))
tangcot();
}// Endif(RB6)
if(!RB7)
{
if(ver==2)
{
if(hor==0)
{
hor=1;
goto hienthi42;
}
if(hor==1)
{
hor=6;
goto hienthi42;
}
if(hor==6)
{
hor=0;
goto hienthi42;
}
hienthi42:
hienthicot2();
goto thoat;
}
if(ver==3)
{
if(hor==1)
{
hor=2;
goto chuyendich43;
}
if(hor==2)
{
hor=3;
goto chuyendich43;
}
if(hor==3)
{
hor=4;
goto chuyendich43;
}
if(hor==4)
{
hor=5;
goto chuyendich43;
}
if(hor==5)
{
hor=1;
goto chuyendich43;
}
if((hor==6)&(user==1))
{
hor=7;
user=0;
goto chuyendich43;
}
if(hor==7)
{
hor=8;
goto chuyendich43;
}
if(hor==8)
{
hor=9;
goto chuyendich43;
}
if(hor==9)
{
hor=7;
goto chuyendich43;
}
chuyendich43:
{
//doctrunggian2();
hienthicot3();
phantich_so(trunggian2);
// doctrunggian2();
}
} //If (ver==3)
}// Endif(RB7)
Thoat:
RBIF=0; //Xoa co ngat RB
} // Ket thuc if co ngat
}// Ket thuc ham void
trong hàm phục vụ ngắt mình gọi đến khá nhiều hàm con. Khi chương trình chính không làm gì, chỉ thiết lập timer hoặc mình bỏ hẳn hàm phục vụ ngắt khỏi chương trình và trong chương trình chính cho gọi đến các hàm con khác thì timer chạy đúng như mong muốn. nhưng khi để hàm phục vụ ngắt và trong chương trình chính có gọi đến chương trình con đã được gọi trong hàm phục vụ ngắt thì thời gian ngắt của timer lại không chính xác nữa.
mình đã thử độc lập riêng timer thì hoàn toàn đúng.
mong được mọi người giúp đỡ. mình cảm ơn nhiều.
bien_van_khat
04-03-2008, 02:37 PM
CCS C không hỗ trợ reentrant, do đó khi 1 chuơng trình con được gọi đồng thời trong chương trình chính và trong trình phục vụ ngắt thì CCS sẽ sinh mã để tự động che ngắt khi vào chương trình con đó để tránh reentrant.
Với trường hợp của bạn có 2 hiệu ứng làm trễ ngắt timer:
Thứ 1: khi vào chương trình con được gọi chung, CCS sẽ che ngắt global, do đó ngắt timer ko đc xảy ra, làm ngắt timer đến trễ so với thực tế.
Thứ 2: Trình phục vụ ngắt thay đổi mức trên PORTB của bạn quá dài, vì trong thời gian đang thực thi trình này thì ngắt nói chung và ngắt timer nói riêng ko thể xảy ra, nên làm trễ ngắt timer.
Về khái niệm reentrant (vào lại).
Bạn có thể tưởng tượng một chương trình con A đang được chạy trong chương trình chính, ngắt xảy ra và A lại đc gọi bởi trình phục vụ ngắt. Lúc này sẽ có một số vấn đề phát sinh:
1 - Không gian bộ nhớ cấp cho các biến của A: nếu linker cấp phát tĩnh các biến này thì coi như tiêu. Với pic16F, cấp phát động bộ nhớ (dùng stack) là điều phức tạp vì hardware ko hỗ trợ nhiều cho truy xuất bộ nhớ gián tiếp, mình ko có thời gian disassembly nhưng tin chắc là CCS ko làm điều này (CCS ko hỗ trợ đệ quy).
2 - Các tác vụ về IO hoặc về biến tốn nhiều chu kỳ máy khi bị ngắt giữa chừng cũng coi như tiêu.
anhvietqx
05-03-2008, 12:57 AM
thanks!!! rat bo ich!
bean984
13-03-2008, 09:31 AM
thanks anh nhiều!!
nhưng em vẫn chưa hiểu lắm về reentrant. anh có tài liệu j nói về vấn đề này không?
vấn đề nữa là trình phục vụ ngắt trên port B của em có lẽ là không rút ngắn được bao nhiêu.vậy có cách nào để tính thời gian ngắt của timer không?
bean984
17-03-2008, 10:15 AM
cho em hỏi một vấn đề nữa nhé.
hiện tại chương trình của em cần thêm một số modul nữa, nhưng khi thêm vào và dịch thì nó thông báo là hết RAM mặc dù trước đó ctrinh mới dùng hết khoảng hơn 60% RAM.
có ai biết về vấn đề này xin giúp em với, làm sao để có thể dịch được nhiều hơn?
bien_van_khat
17-03-2008, 04:42 PM
thanks anh nhiều!!
nhưng em vẫn chưa hiểu lắm về reentrant. anh có tài liệu j nói về vấn đề này không?
vấn đề nữa là trình phục vụ ngắt trên port B của em có lẽ là không rút ngắn được bao nhiêu.vậy có cách nào để tính thời gian ngắt của timer không?
Bạn vào google tìm với từ khóa reentrant, có rất nhiều topic về vấn đề này.
Về timer, mình nghĩ bạn nên đưa phần quét phím ra chương trình chính, khi có ngắt INT_RB, bạn set cờ báo cho chuơng trình chính kiểm tra phím bấm, lúc này ngắt timer vẫn xảy ra được
bean984 cho em hỏi một vấn đề nữa nhé.
hiện tại chương trình của em cần thêm một số modul nữa, nhưng khi thêm vào và dịch thì nó thông báo là hết RAM mặc dù trước đó ctrinh mới dùng hết khoảng hơn 60% RAM.
có ai biết về vấn đề này xin giúp em với, làm sao để có thể dịch được nhiều hơn?
Bạn định thêm vào module gì?
auto_control
22-03-2008, 12:49 AM
mời tìm hiểu về pic cho mình hỏi có cách tạo ra cấu trúc truy nhập kiểu bảng (db ....)như đối với 8051 không .và tổ chức như thế nào/Mong trả lời của các bạn và các tiền bối
namqn
22-03-2008, 12:55 AM
mời tìm hiểu về pic cho mình hỏi có cách tạo ra cấu trúc truy nhập kiểu bảng (db ....)như đối với 8051 không .và tổ chức như thế nào,
Bạn đặt câu hỏi này trong luồng về CCS C cho PIC, xem ra không thích hợp. Các ngôn ngữ cấp cao, trong trường hợp này là ngôn ngữ C, đã xử lý các cấu trúc dữ liệu cho người lập trình rồi, cho nên không cần quan tâm xem tổ chức như thế nào.
Câu hỏi của bạn nên được post ở luồng cơ bản về PIC và vi điều khiển, và sử dụng hợp ngữ. Bạn có thể đọc tài liệu hướng dẫn của MPASM để thấy có thể dùng DT, DB, và DW để định nghĩa các bảng dữ liệu.
Thân,
auto_control
22-03-2008, 01:16 AM
làm phiền trưởng lão lần nữa.nếu dùng CCs thì việc xử lý kiểu bảng này ra sao,chẳng hạn đệ muốn cho led7 hiển thị đếm ,thì khi dùng truy nhập bảng có vẻ nhanh hơn(thiển ý)
thanks!
namqn
22-03-2008, 06:40 PM
làm phiền trưởng lão lần nữa.nếu dùng CCs thì việc xử lý kiểu bảng này ra sao,chẳng hạn đệ muốn cho led7 hiển thị đếm ,thì khi dùng truy nhập bảng có vẻ nhanh hơn(thiển ý)
thanks!
Mời bạn download tài liệu hướng dẫn của CCS C ở link sau:
http://www.ccsinfo.com/downloads/CReferenceManual.pdf
Ở trang 268 có ví dụ về bảng hằng số trong flash (ROM) của PIC, bạn có thể dựa vào đó để làm bảng giải mã hiển thị cho LED 7 đoạn chẳng hạn.
Thân,
bean984
24-03-2008, 02:48 PM
cho em hoi câu này
ý nghĩa của khai báo #fuses PUT là gì ?
nó ảnh hưởng đến timer như thế nào?(kết quả timer hoạt động thay đổi như thế nào khi có và không có khai báo trên)
em cảm ơn nhìu!
bien_van_khat
24-03-2008, 04:36 PM
cho em hoi câu này
ý nghĩa của khai báo #fuses PUT là gì ?
nó ảnh hưởng đến timer như thế nào?(kết quả timer hoạt động thay đổi như thế nào khi có và không có khai báo trên)
em cảm ơn nhìu!
PUT = Power Up Timer (bạn xem trong view/valid fuses của PCW)
Nói đơn giản là khi PIC đc cấp nguồn, Power Up Timer sẽ chờ 1 khoảng thời gian mới cho PIC chạy (thực thi code), khoảng thời gian chờ này nhằm đảm bảo nguồn cấp cho PIC ổn định.
Power Up Timer ko liên quan gì đến các timer của PIC.
LeDuc
24-03-2008, 06:19 PM
PUT = Power Up Timer (bạn xem trong view/valid fuses của PCW)
Nói đơn giản là khi PIC đc cấp nguồn, Power Up Timer sẽ chờ 1 khoảng thời gian mới cho PIC chạy (thực thi code), khoảng thời gian chờ này nhằm đảm bảo nguồn cấp cho PIC ổn định.
Power Up Timer ko liên quan gì đến các timer của PIC.
Cho em hỏi câu này hơi chuối ? làm sao để nạp vào eeprom của 16f887 ? nạp qua đường nào? qua chân nào của Pic ?
Em cần nạp một mảng giá trị vào eeprom trước.cũng khoản 210 byte . Và sau này chường trình chính chỉ việc sử dụng các giá trị trong các ô nhớ của eeprom để xử lý mà thôi ....
Mong các huynh giúp đỡ !!
Thanks for all !
namqn
24-03-2008, 06:21 PM
Cho em hỏi câu này hơi chuối ? làm sao để nạp vào eeprom của 16f887 ? nạp qua đường nào? qua chân nào của Pic ?
Em cần nạp một mảng giá trị vào eeprom trước.cũng khoản 210 byte . Và sau này chường trình chính chỉ việc sử dụng các giá trị trong các ô nhớ của eeprom để xử lý mà thôi ....
Mong các huynh giúp đỡ !!
Thanks for all !
Bạn nạp thông tin cho EEPROM cùng lúc với nạp chương trình cho PIC, tất nhiên là thông qua ICSP. Chương trình của bạn cũng có thể tự ghi vào EEPROM, nếu bạn viết chương trình để cung cấp các chức năng đó.
Thân,
ha_vy_cson
26-03-2008, 08:27 PM
các bác ơi! cho em hỏi một tý...
em đang lập trình giao tiếp giữa pc và pic 16f877a, em muon truyen một chuổi từ máy tính bằng vb6 đến pic thi nên viết code trên VB như thế nào và viết hàm nhận trong ccs như thế nào........
LeDuc
26-03-2008, 09:12 PM
Bạn nạp thông tin cho EEPROM cùng lúc với nạp chương trình cho PIC, tất nhiên là thông qua ICSP. Chương trình của bạn cũng có thể tự ghi vào EEPROM, nếu bạn viết chương trình để cung cấp các chức năng đó.
Thân,
Vấn đề là em muốn nap độc lập , mà kô ảnh hường đến chương trình chính có được ko anh ?
Vì một yêu cầu đặt ra là kô thay đổi chương trình chính mà chỉ việc thay đổi giá trị trong các ô nhớ của eeprom . Chương trình chính làm việc khác nhau ứng với các giá trị khác nhau trong vùng nhớ eeprom....
Mong các huynh giúp đỡ .
Thanks for all !
namqn
26-03-2008, 10:19 PM
Vấn đề là em muốn nap độc lập , mà kô ảnh hường đến chương trình chính có được ko anh ?
Vì một yêu cầu đặt ra là kô thay đổi chương trình chính mà chỉ việc thay đổi giá trị trong các ô nhớ của eeprom . Chương trình chính làm việc khác nhau ứng với các giá trị khác nhau trong vùng nhớ eeprom....
Mong các huynh giúp đỡ .
Thanks for all !
Đây chỉ là vấn đề bạn sử dụng phần mềm nạp chương trình ra sao. Đa số các phần mềm đều cho phép bạn chọn lựa vùng nhớ được cập nhật. Lấy ví dụ WinPic800, bạn vào menu Setting, chọn Software, sau đó nhấn nút ICSP Mode. Bạn sẽ thấy phía dưới có những check box cho các vùng nhớ khác nhau. Nếu bạn uncheck tất cả các vùng nhớ, chỉ để lại Data, thì WinPic800 sẽ chỉ cập nhật Data EEPROM khi bạn ra lệnh nạp cho PIC.
Một số phần mềm thì có lệnh ghi vào từng vùng nhớ riêng, và 1 lệnh để ghi tất cả các vùng nhớ. Nói chung, bạn tìm hiểu kỹ phần mềm đang dùng để nạp chip thì sẽ làm được điều bạn muốn.
Thân,
LeDuc
27-03-2008, 02:07 AM
Đây chỉ là vấn đề bạn sử dụng phần mềm nạp chương trình ra sao. Đa số các phần mềm đều cho phép bạn chọn lựa vùng nhớ được cập nhật. Lấy ví dụ WinPic800, bạn vào menu Setting, chọn Software, sau đó nhấn nút ICSP Mode. Bạn sẽ thấy phía dưới có những check box cho các vùng nhớ khác nhau. Nếu bạn uncheck tất cả các vùng nhớ, chỉ để lại Data, thì WinPic800 sẽ chỉ cập nhật Data EEPROM khi bạn ra lệnh nạp cho PIC.
Một số phần mềm thì có lệnh ghi vào từng vùng nhớ riêng, và 1 lệnh để ghi tất cả các vùng nhớ. Nói chung, bạn tìm hiểu kỹ phần mềm đang dùng để nạp chip thì sẽ làm được điều bạn muốn.
Thân,
Dạ , em hiểu rồi .
Em đã nạp được rồi .rất cảm ơn anh .
Nhưng em vẫn còn một vướng mắc ,hiện giờ mình chỉ nạp data vào riêng vùng eeprom .
Giả sử em muốn nạp giá tri 1-->255, tương ứng với ô nhớ từ 1-->255, vậy giá trị nạp này mình phải viết làm sao để có được file hex nạp riêng vào vùng nhớ eeprom đây?( chương trình chính là mình ko đụng đến rồi ...
Mong các anh chỉ giúp ..
Thanks for all !!
namqn
27-03-2008, 02:44 AM
Dạ , em hiểu rồi .
Em đã nạp được rồi .rất cảm ơn anh .
Nhưng em vẫn còn một vướng mắc ,hiện giờ mình chỉ nạp data vào riêng vùng eeprom .
Giả sử em muốn nạp giá tri 1-->255, tương ứng với ô nhớ từ 1-->255, vậy giá trị nạp này mình phải viết làm sao để có được file hex nạp riêng vào vùng nhớ eeprom đây?( chương trình chính là mình ko đụng đến rồi ...
Mong các anh chỉ giúp ..
Thanks for all !!
Bạn đọc tài liệu hướng dẫn của CCS C, mục nói về #rom (trong phần Preprocessor Directives). Ở đó đã có ví dụ cách đặt các giá trị cho EEPROM.
Thân,
ha_vy_cson
30-03-2008, 08:06 PM
các bác ơi! cho em hỏi một tý...
em đang lập trình giao tiếp giữa pc và pic 16f877a, em muon truyen một chuổi từ máy tính bằng vb6 đến pic thi nên viết code trên VB như thế nào và viết hàm nhận trong ccs như thế nào........
bean984
23-04-2008, 05:42 PM
cho mình hỏi
port c của con 16f877a này có gì đặc biệt không vậy?
mình dùng 3 chân RC0,RC1,RC2 để nối đến 3 chân điều khiển LCD.nhưng tại sao khi mình không set_tris cổng này mà vẫn điều khiển được LCD.
mình hỏi một câu nữa nhé.
khi dùng các chân RC6,RC7 để truyền nhận thì không được set_tris cổng C? nếu vậy muốn dùng các chân khác với mục đích I/O thì làm ntn?
mình cảm ơn nhiều!!!
thaithienanh
23-04-2008, 07:04 PM
cho mình hỏi
port c của con 16f877a này có gì đặc biệt không vậy?
mình dùng 3 chân RC0,RC1,RC2 để nối đến 3 chân điều khiển LCD.nhưng tại sao khi mình không set_tris cổng này mà vẫn điều khiển được LCD.
mình hỏi một câu nữa nhé.
khi dùng các chân RC6,RC7 để truyền nhận thì không được set_tris cổng C? nếu vậy muốn dùng các chân khác với mục đích I/O thì làm ntn?
mình cảm ơn nhiều!!!
Port C của 16f877a tích hợp các modul truyền nhận dữ liệu theo các chuẩn khác nhau như I2C, SPI, .... chứ cũng chẳng có gì đặc biệt cả :o
- Bạn không set_tris nhưng vẫn điều khển được LCD là vì trình dịch CCS hỗ trợ, nó sẽ set_tris giùm bạn ở mỗi câu lệnh liên quan đến I/O => tốc độ xử lý và bộ nhớ giảm đi đáng kể do hành động set_tris lập đi lập lại nhiều lần dẫn đến dài dòng thừa thải :o code đơn giản thì không sao chứ nếu code đòi hỏi tốc độ và dung lượng bộ nhớ lớn thì mình khuyên nên dùng set_tris.
- Bạn dùng lệnh set_tris thì không giao tiếp đuợc với PC qua chuẩn 232, mình cũng chưa để ý cái này, nhưng mình nghĩ chắc chắn là đuợc chứ :o, bạn nên xem lại set i/o của bạn cho hai chân RC6 và RC7 đã đúng chưa :o, lưu ý lại với bạn ở đây chân RC6 là chân truyền (tranmister) tức ngõ ra và chân RC7 là chân nhận (Receiver) tức ngõ vào. Với lại trong câu lệnh set tris để set ngõ vào thì dùng bit (1), và ngõ ra tương ứng với bit (0).
Còn bạn gì ở trên kia muốn tìm hiểu giao tiếp với PC thì tìm lại trên diễn đàn nhé, có quá nhiều bài viết hướng dẫn và cả ví dụ mẫu về nó rồi đấy :o
Chúc các bạn thành công.
Thân.
bean984
24-04-2008, 10:13 AM
- Bạn không set_tris nhưng vẫn điều khển được LCD là vì trình dịch CCS hỗ trợ, nó sẽ set_tris giùm bạn ở mỗi câu lệnh liên quan đến I/O => tốc độ xử lý và bộ nhớ giảm đi đáng kể do hành động set_tris lập đi lập lại nhiều lần dẫn đến dài dòng thừa thải :o code đơn giản thì không sao chứ nếu code đòi hỏi tốc độ và dung lượng bộ nhớ lớn thì mình khuyên nên dùng set_tris.
nhưng mình đã thử lại I/O của port C bằng cách nháy led. Hoàn toàn không được nếu không set_tris. và với các port khác cũng vậy????
falleaf
24-04-2008, 12:00 PM
F khoá luồng này:
- Trình dịch CCS C các phiên bản mới có một số thay đổi về lệnh, bài tutorial của nhh hiện nay không còn phù hợp với người dùng các phiên bản mới (sẽ có một số chỗ sai).
- Luồng quá dài và quá lan man, cần phải chốt lại.
- Nếu bạn nào có những câu hỏi liên quan tới CCS C thì ta tiếp tục làm việc với nó ở luồng tới đây.
CCS C cho PIC/dsPIC từ phiên bản 4.xxx (http://www.picvietnam.com/forum/showthread.php?t=2296)
Chúc vui
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.