PDA

View Full Version : dsPIC Tutorial 3-Đọc ngõ vào và giao tiếp LCD


namqn
03-08-2006, 11:05 PM
Đây là tutorial tiếp theo cho dsPIC, viết trong ASM30. Vài ngày tới tôi sẽ post các source code viết bằng C30 cho các tutorial đã viết. Các bạn theo dõi trong các luồng tương ứng của các tutorial đã post.

Trong tutorial 3 cho dsPIC, thông qua một ví dụ về đọc trạng thái các công tắc nối vào dsPIC và hiển thị trạng thái trên LCD, tôi minh hoạ cách đọc ngõ vào số của dsPIC, và cách giao tiếp dsPIC với LCD. Tôi cũng đã giới thiệu cách viết macro và cách định thời bằng ngắt với thời gian xử lý ngắt tối thiểu.

Link để download tutorial:
http://picvietnam.com/download/upload/namqn/TUT04.01.PVN.NQNT.180706.pdf

Các tập tin nguồn và hex được đặt trong tập tin nén sau:
http://picvietnam.com/download/upload/namqn/Vidu3.zip

Chúc các bạn thành công!

Thân,

namqn
08-08-2006, 08:02 PM
Mã nguồn viết trong C30 (và các tập tin .hex) cho các ví dụ trong tutorial này có thể download ở đây:
http://picvietnam.com/download/upload/namqn/Vidu3C30.zip

Chúc thành công!

Thân,

ITpro
12-10-2006, 10:59 PM
Anh ơi,sao em ko down được anh ah.Anh xem lại link giúp em cái.
Thanks

ITpro
12-10-2006, 11:01 PM
Em mới nghiên cứu về DSpic.Trước em có làm về con 16F877A.Vào đây thấy hay quá,nhưng em vào mấy cái link của anh thì toàn báo lỗi.

namqn
13-10-2006, 12:07 AM
Em mới nghiên cứu về DSpic.Trước em có làm về con 16F877A.Vào đây thấy hay quá,nhưng em vào mấy cái link của anh thì toàn báo lỗi.
Host lưu trữ được chuyển sang tailieuvietnam.net rồi, các bạn tải bằng các tập tin gửi kèm ở đây nhé.

Thân,

typhn
04-12-2006, 10:50 PM
Anh cho em hỏi dòng config : PWMxL_ACT_HI & PWMxH_ACT_HI
có nghĩa là gì hả anh?

namqn
04-12-2006, 11:22 PM
Anh cho em hỏi dòng config : PWMxL_ACT_HI & PWMxH_ACT_HI
có nghĩa là gì hả anh
Có nghĩa là các chân PWMxL và các chân PWMxH tích cực ở mức cao (tuy nhiên các chức năng của module PWM không được sử dụng trong tutorial này, do đó tích cực cao hay thấp không ảnh hưởng đến kết quả chạy chương trình).

Thân,

longho559
01-03-2007, 11:16 AM
Anh Nam cho em hỏi :
const unsigned char __attribute__ ((space(psv), address (0x0400)))
//Chuoi ky tu se xuat ra LCD
Chuoi1[]=" Hello World "; //Chuoi ky tu se duoc xuat ra LCD
_PSV=1;
PSVPAG = __builtin_psvpage(Chuoi1);

đoạn source trên dùng để làm gì, nếu muốn xuất thêm Chuồi 2 vào dòng thứ 2 của LCD thì làm sao? Anh có thể cho em biết trang web nào hướng dẫn lập trình C cho dspic ko? Thank a lot!

namqn
01-03-2007, 06:02 PM
Dòng lệnh thứ nhất khai báo vùng nhớ (hằng) có thể truy xuất thông qua PSV ở địa chỉ 0x0400. Dòng lệnh thứ hai khai báo một chuỗi hằng trong không gian đó. Dòng lệnh thứ ba bật chế độ truy xuất thông qua PSV. Dòng thứ tư thiết lập thanh ghi trang trước khi truy xuất bằng PSV. Không gian địa chỉ flash của dsPIC là 24-bit, trong khi các thanh ghi chỉ số dùng để truy xuất dữ liệu là 16-bit, do đó cần có một thanh ghi trang chứa 8 bit cao hơn của địa chỉ.

Để xuất một chuỗi khác vào dòng thứ hai của LCD thì bạn chỉ cần khai báo chuỗi mới đó, truy xuất chuỗi đó thay vì chuỗi thứ nhất trong vòng lặp xuất ra dòng thứ hai của LCD.

Hiện thời chỉ có một vài quyển sách về lập trình dsPIC bằng ngôn ngữ cấp cao được bán, tôi chưa tìm được trang web nào hướng dẫn việc này. Đó cũng là 1 lý do khiến tôi viết những tutorial này, dù rằng tôi phải vừa học vừa viết.

Thân,

vtt
20-03-2007, 04:32 PM
Chào các anh!
Em cung dang tim hieu ve dsPic và có tham khảo qua một số Tutorial của anh Nam. Em co làm thử một ví dụ là đọc trạng thái của Switch và hiện thị kết quả đọc đó ra Led đơn. Nhưng không hiểu sao em nó không chạy xin các anh chi giùm. Em có upload cả phần cứng lẫn phần mềm lên mong các anh bớt chút thời gian và cho lời giải thích!
Thank!
Không hiểu sao em không upload được
Em mô tả qua phần cứng vậy:
Các led đơn (7Led) được nối với PortF của dsPic30f4013, chân kia của Led đơn nối với trở 100 và được nối xuống đất.
8 chân của switch thì được nối với chân RB0-RB7
và chương trình chính như sau:

void main()
{
int temp;
while(1) {
temp = PORTB;
temp = temp & 0x00FF;
LATE = temp;
}
}

namqn
20-03-2007, 06:09 PM
Chào các anh!
Em cung dang tim hieu ve dsPic và có tham khảo qua một số Tutorial của anh Nam. Em co làm thử một ví dụ là đọc trạng thái của Switch và hiện thị kết quả đọc đó ra Led đơn. Nhưng không hiểu sao em nó không chạy xin các anh chi giùm. Em có upload cả phần cứng lẫn phần mềm lên mong các anh bớt chút thời gian và cho lời giải thích!
Thank!
Không hiểu sao em không upload được
Em mô tả qua phần cứng vậy:
Các led đơn (7Led) được nối với PortF của dsPic30f4013, chân kia của Led đơn nối với trở 100 và được nối xuống đất.
8 chân của switch thì được nối với chân RB0-RB7
và chương trình chính như sau:

void main()
{
int temp;
while(1) {
temp = PORTB;
temp = temp & 0x00FF;
LATE = temp;
}
}
- Bạn mô tả cách nối của switch vẫn chưa đủ, switch nối từ RBx xuống GND, và từ RBx có trở kéo lên Vdd? hay là nối kiểu khác?
- Với PIC và dsPIC thì nhất định phải cấu hình đầy đủ rồi mới viết chương trình, có nhiều bạn gặp nhiều lỗi khó hiểu, và đó là do cấu hình chip chưa đúng.
- Bạn nối LED vào port F nhưng chương trình lại xuất ra port E!

Thân,

nguyen.geo
20-06-2007, 04:50 PM
- Bạn mô tả cách nối của switch vẫn chưa đủ, switch nối từ RBx xuống GND, và từ RBx có trở kéo lên Vdd? hay là nối kiểu khác?
- Với PIC và dsPIC thì nhất định phải cấu hình đầy đủ rồi mới viết chương trình, có nhiều bạn gặp nhiều lỗi khó hiểu, và đó là do cấu hình chip chưa đúng.
- Bạn nối LED vào port F nhưng chương trình lại xuất ra port E!

Thân,

Bác Nam Ơi! Bác có thể trả lời em câu hỏi ở chổ này với :
http://www.picvietnam.com/forum/showthread.php?t=1139&page=2

và Bác cho em hỏi Bác dùng Protues bản bao nhiêu thế Bác và có thể Download ở chỗ nào hả bác. Em đang dùng Protues 6.7 nhưng em tìm không thấy con DSPIC30F4011 mà trong bài hướng dẫn em thấy Bác vẽ.

namqn
20-06-2007, 06:04 PM
Bác Nam Ơi! Bác có thể trả lời em câu hỏi ở chổ này với :
http://www.picvietnam.com/forum/showthread.php?t=1139&page=2

và Bác cho em hỏi Bác dùng Protues bản bao nhiêu thế Bác và có thể Download ở chỗ nào hả bác. Em đang dùng Protues 6.7 nhưng em tìm không thấy con DSPIC30F4011 mà trong bài hướng dẫn em thấy Bác vẽ.
Phần câu hỏi bên luồng kia tôi đã trả lời rồi, bạn nên xem tutorial 1 trong box này.

Tôi dùng Proteus 6.9 SP1, phiên bản licensed của trường (Sheffield University). Symbol của dsPIC30F4012 đó là tôi tự vẽ ra, không có sẵn trong thư viện của Proteus đâu.

Thân,

footballer
17-03-2008, 06:05 PM
Anh Nam cho em hỏi: trong code vidu3_1.s có dòng config như sau:
config __FOSC, CSW_FSCM_OFF & FRC_PLL4 ;Clock = 32 MHz
Em đọc trong tài liệu dsPIC30F Family Reference Manual thì thấy với chế độ FRC_PLL4 thì clock chỉ bằng 7.37*4 MHz thôi, sao lại có clock=32MHz.

namqn
17-03-2008, 06:45 PM
Anh Nam cho em hỏi: trong code vidu3_1.s có dòng config như sau:
config __FOSC, CSW_FSCM_OFF & FRC_PLL4 ;Clock = 32 MHz
Em đọc trong tài liệu dsPIC30F Family Reference Manual thì thấy với chế độ FRC_PLL4 thì clock chỉ bằng 7.37*4 MHz thôi, sao lại có clock=32MHz.
dsPIC30F4012 sample mà tôi đã dùng cho tutorial (SX năm 2004) có tần số danh định của FRC là 8 MHz, các phiên bản silicon sau này mới điều chỉnh lại thành 7.37 MHz (được phản ánh trong datasheet phiên bản DS70135D trở đi).

Tutorial được post vào tháng 08/2006 mà bạn.

Thân,

babyrock
24-04-2008, 01:19 AM
Bác namqn cho em hỏi tí, em vừa mới làm quen với dsPic em đang làm với con 30F3012, em sử dụng bộ kit dsPICDEM™ 2 DEVELOPMENT BOARD, thì có sử dụng được chương trình của bác không vậy.
Cảm ơn bác

namqn
24-04-2008, 01:51 AM
Bác namqn cho em hỏi tí, em vừa mới làm quen với dsPic em đang làm với con 30F3012, em sử dụng bộ kit dsPICDEM™ 2 DEVELOPMENT BOARD, thì có sử dụng được chương trình của bác không vậy.
Cảm ơn bác
Bạn vẫn có thể sử dụng các chương trình tôi đã viết, tuy nhiên, do dsPIC30F3012 có ít chân hơn so với dsPIC30F4012, bạn có thể phải giảm bớt số chân nối vào các switch. Giao tiếp LCD 4-bit như tôi đã thực hiện cần có ít nhất 7 chân I/O.

Bạn sẽ cần phải định nghĩa lại các chân kết nối vào LCD theo như phần cứng của bạn, cấu hình lại chip cho thích hợp với dsPICDEM 2 và biên dịch lại chương trình. Vì bạn mới làm quen với dsPIC, bạn nên dùng các mã nguồn C30 mà tôi đã cung cấp, thay vì dùng các mã nguồn hợp ngữ.

Thân,

tungtuantu
11-11-2008, 09:51 AM
Bác namqn cho em hỏi, để định nghĩa lại các chân dât ko cùng 1 cổng như của bác, thì các code sau phải thay đổi lại như nào ah, ví dụ của em là D4 là C14, D5 là E8, D6 là D2, D7 là D1. Em dùng 30F4011
Trong code của bác dấu "_" có nghĩa là j thế ah, ví dụ _TRISF3 = 0.
Em chưa hiểu về cách cấu hình cho dspic, bác có thể nói rõ thêm ko ah,
Em đã xuất dc chữ ra LCD với CCS nhung em vẫn bị vài vấn đề như, em cho 1 ja trị value++ để xuất ra LCD thì giá trị ra cứ đến 7 (hoặc ở giá trị khác tùy vào em delay nhanh hay chậm) là reset về 0 đông fthowif lúc đó các kí tự trong LCD bì loạn lên. Hoặc khi em chỉ cho hiện chữ thôi và trong while(1) em chỉ cho nháy led, nhung led chỉ nháy dc 1 lúc rồi lại đứng yên rồi lại nháy tiếp, em đã tắt WDT bằng lênh setup_wdt(WDT_OFF) rồi, thậm chí em cho các bit trong RCON ( thanh ghi về các sự kiện resert) + 0 hết mà vẫn bị.
Nên em thử chuyển qua C30 xem hiện tượng đó còn bị ko. Mong bác giúp em
đây là đoặn em cấu hình cho chip

#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PR //Promiary Oscillator
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES WPSB16 //Watch Dog Timer PreScalar B 1:16
#FUSES WPSA512 //Watch Dog Timer PreScalar A 1:512
#FUSES PUT64 //Power On Reset Timer value 64ms
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV47 //Brownout reset at 4.7V
#FUSES LPOL_HIGH //Low-Side Transistors Polarity is Active-High (PWM 0,2,4 and 6)
//PWM module low side output pins have active high output polar
#FUSES HPOL_HIGH //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
//PWM module high side output pins have active high output polarity
#FUSES NOPWMPIN //PWM outputs drive active state upon Reset
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOCOE //Device will reset into operational mode
#FUSES ICS0 //ICD communication channel 0
#FUSES RESERVED //Used to set the reserved FUSE bits

namqn
11-11-2008, 04:27 PM
Bác namqn cho em hỏi, để định nghĩa lại các chân dât ko cùng 1 cổng như của bác, thì các code sau phải thay đổi lại như nào ah, ví dụ của em là D4 là C14, D5 là E8, D6 là D2, D7 là D1. Em dùng 30F4011
Trong code của bác dấu "_" có nghĩa là j thế ah, ví dụ _TRISF3 = 0.
Em chưa hiểu về cách cấu hình cho dspic, bác có thể nói rõ thêm ko ah,
Em đã xuất dc chữ ra LCD với CCS nhung em vẫn bị vài vấn đề như, em cho 1 ja trị value++ để xuất ra LCD thì giá trị ra cứ đến 7 (hoặc ở giá trị khác tùy vào em delay nhanh hay chậm) là reset về 0 đông fthowif lúc đó các kí tự trong LCD bì loạn lên. Hoặc khi em chỉ cho hiện chữ thôi và trong while(1) em chỉ cho nháy led, nhung led chỉ nháy dc 1 lúc rồi lại đứng yên rồi lại nháy tiếp, em đã tắt WDT bằng lênh setup_wdt(WDT_OFF) rồi, thậm chí em cho các bit trong RCON ( thanh ghi về các sự kiện resert) + 0 hết mà vẫn bị.
Nên em thử chuyển qua C30 xem hiện tượng đó còn bị ko. Mong bác giúp em
đây là đoặn em cấu hình cho chip

#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PR //Promiary Oscillator
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES WPSB16 //Watch Dog Timer PreScalar B 1:16
#FUSES WPSA512 //Watch Dog Timer PreScalar A 1:512
#FUSES PUT64 //Power On Reset Timer value 64ms
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV47 //Brownout reset at 4.7V
#FUSES LPOL_HIGH //Low-Side Transistors Polarity is Active-High (PWM 0,2,4 and 6)
//PWM module low side output pins have active high output polar
#FUSES HPOL_HIGH //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
//PWM module high side output pins have active high output polarity
#FUSES NOPWMPIN //PWM outputs drive active state upon Reset
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOCOE //Device will reset into operational mode
#FUSES ICS0 //ICD communication channel 0
#FUSES RESERVED //Used to set the reserved FUSE bits

Bạn cần viết lại các chương trình xuất dữ liệu và xuất lệnh ra LCD (và chương trình con đọc dữ liệu từ LCD, nếu bạn có dùng nó). Code mà bạn đã post chỉ là phần cấu hình của dsPIC (trong CCS C), trong C30 thì bạn viết tương tự như trong tutorial của tôi. Thông tin về các tổ hợp cấu hình hợp lệ có trong tập tin header của dsPIC (tập tin "p30f4011.h" trong thư mục con "support\dsPIC30F\h" của thư mục cài đặt MPLAB C Compiler for dsPIC DSCs, phiên bản 3.xx).

_TRISF3 được định nghĩa là TRISFbits.TRISF3, cũng trong tập tin .h trên. Chỉ là một kiểu thay thế để viết code ngắn gọn hơn thôi.

Thân,

tungtuantu
11-11-2008, 04:58 PM
bác namqn ơi thế có cách nào định nghĩa 1 byte LCD_DATA gồm có 4 bít LCD_D4, LCD_D5, LCD_D6, LCD_D7, nếu dc thì sửa chân trong file LCD của bác sẽ đơn giản hơn nhiều,

namqn
11-11-2008, 05:22 PM
bác namqn ơi thế có cách nào định nghĩa 1 byte LCD_DATA gồm có 4 bít LCD_D4, LCD_D5, LCD_D6, LCD_D7, nếu dc thì sửa chân trong file LCD của bác sẽ đơn giản hơn nhiều,
Theo tôi biết thì không làm được như vậy. Bạn chỉ cần thay lệnh xuất 1 nibble trong các chương trình con ghi dữ liệu/lệnh ra LCD bằng 4 lệnh đặt trạng thái bit thôi mà. Tương tự, đọc dữ liệu từ 4 bit riêng biệt thay vì đọc 1 nibble từ LCD về cho chương trình con đọc dữ liệu từ LCD.

Thân,

tungtuantu
13-11-2008, 06:53 PM
bác namqn, Em đã sửa file của bác để chạy được với cách nối chân LCD của em, đây là đoặn code

#include "p30f4011.h"

_FOSC(CSW_FSCM_OFF & FRC_PLL4); //Clock = 32 MHz
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)

#define ms_count 125 //So dem tuong ung voi 1 ms, cho timer 1


#define LCD_EN _LATC13 //Tin hieu Enable cho LCD, chan RE8
#define LCD_RW _LATB8 //Tin hieu Read/Write cho LCD, chan RD0
#define LCD_RS _LATB7 //Tin hieu Reset cho LCD, chan RD1

#define LCD_D4 _LATC14 //Cac tin hieu Data cho LCD, chan (D4..D7)
#define LCD_D5 _LATE8
#define LCD_D6 _LATD1
#define LCD_D7 _LATD3

#define TRIS_LCD_D4 _TRISC14 //Tristate cua cac tin hieu Data cho LCD
#define TRIS_LCD_D5 _TRISE8
#define TRIS_LCD_D6 _TRISD1
#define TRIS_LCD_D7 _TRISD3

#define LCD_clear 0x01 //Xoa man hinh LCD
#define LCD_home 0x02 //Tro ve dau dong
#define LCD_normal 0x06 //Che do nhap du lieu binh thuong
#define LCD_normal_s 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_off 0x08 //Tat man hinh
#define LCD_on 0x0C //Bat man hinh
#define LCD_on_crsr 0x0E //Bat man hinh va con tro
#define LCD_on_blink 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_4b2l 0x28 //Che do 2 dong, giao tiep 4 bit du lieu
#define LCD_homeL1 0x80 //Ve dau dong 1
#define LCD_homeL2 0xC0 //Ve dau dong 2

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void); //Khoi tao cac cong I/O
void Init_TMR1(void); //Khoi tao Timer 1
void Delay_ms(unsigned int); //Tao tre mot so ms
void Init_LCD(void); //Khoi tao LCD
void LCD_cmd4(unsigned char); //Xuat lenh ra LCD qua giao tiep 4-bit
void LCD_dat4(unsigned char); //Xuat du lieu ra LCD qua giao tiep 4-bit

//Bang hang so trong ROM
char chuoi1[]="Hello world!"; //Chuoi ky tu se duoc xuat ra LCD

//Cac bien toan cuc
unsigned char time_out,idx;

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
_TRISE3 = 0;
Init_TMR1(); //Khoi tao cho TMR1
Init_PORTS(); //Khoi tao cac cong I/O
idx = 0;
Init_LCD();
Delay_ms(500);

LCD_dat4('E');

while (1) {
_LATE3=1;
Delay_ms(250); //Vong lap chinh
_LATE3=0;
Delay_ms(250);
};
}

//Chuong trinh con khoi tao Timer 1
//TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
//------------------------------------------------------------------------------
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = ms_count; //TMR1 tran moi ms
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x0020; //Dung fcy lam clock, prescale = 1:64, tat Timer 1
_T1IE = 1; //Cho phep ngat Timer 1
}

//Chuong trinh con khoi tao cac cong I/O, de noi voi LED
//------------------------------------------------------------------------------
void Init_PORTS(void)
{
LCD_D4 = 0; //Xoa cac bit chot du lieu LCD
LCD_D5 = 0;
LCD_D6 = 0;
LCD_D7 = 0;

TRIS_LCD_D4 = 0; //Cac chan du lieu LCD la ngo ra
TRIS_LCD_D5 = 0;
TRIS_LCD_D6 = 0;
TRIS_LCD_D7 = 0;

LCD_EN = 0;
_TRISC13 = 0; //RE8 la ngo ra, noi vao Enable cua LCD
LCD_RW = 0;
_TRISB8 = 0; //RD0 la ngo ra, noi vao R/W cua LCD
LCD_RS = 0;
_TRISB7 = 0; //RD1 la ngo ra, noi vao Reset cua LCD
}

//Chuong trinh con delay bang timer 1, nhan 1 tham so la so ms can delay
//------------------------------------------------------------------------------
void Delay_ms(unsigned n) {
PR1 = n*ms_count; //Dat nguong tran vao PR1
time_out = 0; //Xoa co het thoi gian cho
T1CONbits.TON = 1; //Bat timer 1
while (time_out == 0); //Cho den khi het thoi gian cho
T1CONbits.TON = 0; //Tat timer 1
TMR1 = 0;
}

//Chuong trinh con khoi tao module LCD
//------------------------------------------------------------------------------
void Init_LCD(void) {
LCD_cmd4(LCD_4b2l); //Dat che do giao tiep 4-bit, man hinh 2 dong
Delay_ms(1);
LCD_cmd4(LCD_off); //Tat man hinh
Delay_ms(1);
LCD_cmd4(LCD_normal); //Che do nhap du lieu binh thuong
Delay_ms(1);
LCD_cmd4(LCD_on_blink); //Bat man hinh, hien con tro nhap nhay
Delay_ms(1);
LCD_cmd4(LCD_clear); //Xoa man hinh
Delay_ms(5);

}

//Chuong trinh con xuat lenh o che do 4 bit
//------------------------------------------------------------------------------
void LCD_cmd4(unsigned char cmd) {
unsigned temp1, i;
LCD_RW = 0;
LCD_RS = 0; //Dat che do xuat lenh
temp1 = cmd >> 4; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp1 & 1; //Xuat 4 bit cao
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp1 = cmd & 0x0F; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp1 & 1; //Xuat 4 bit thap
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh con xuat du lieu o che do 4 bit
//------------------------------------------------------------------------------
void LCD_dat4(unsigned char dat) {
unsigned temp2, i;
LCD_RW = 0;
LCD_RS = 1; //Dat che do xuat du lieu
temp2 = dat >> 4; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp2 & 1; //Xuat 4 bit cao
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp2 = dat & 0x0F; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp2 & 1; //Xuat 4 bit thap
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh xu ly ngat Timer 1
//------------------------------------------------------------------------------
void _ISR _T1Interrupt(void) {
_T1IF = 0; //Xoa co ngat
time_out = 1;
}



Nhưng có vấn đề là em chỉ xuất được 1 kí tự thôi và lúc nào con trỏ cũng nháy nháy (làm sao để tắt dc cái nháy này), nếu trong hàm main em thay LCD_dat4('E'); bằng LCD_dat4("PIC30F4011"); thì ko hiện dc j cả. Vậy làm sao để xuất ra 1 chuỗi mà ko liên quan đến PSV (vì em để nguyên code của bác phần này thì dịch báo lỗi), có cách nào mà mình xuất ra chuỗi với lệnh LCD_dat4("PIC30F4011") , cách này ở bên CCS dùng rất tiện và ngắn gọn.
Bác xem hộ em nhé

namqn
13-11-2008, 07:10 PM
bác namqn, Em đã sửa file của bác để chạy được với cách nối chân LCD của em, đây là đoặn code
...
Nhưng có vấn đề là em chỉ xuất được 1 kí tự thôi và lúc nào con trỏ cũng nháy nháy (làm sao để tắt dc cái nháy này), nếu trong hàm main em thay LCD_dat4('E'); bằng LCD_dat4("PIC30F4011"); thì ko hiện dc j cả. Vậy làm sao để xuất ra 1 chuỗi mà ko liên quan đến PSV (vì em để nguyên code của bác phần này thì dịch báo lỗi), có cách nào mà mình xuất ra chuỗi với lệnh LCD_dat4("PIC30F4011") , cách này ở bên CCS dùng rất tiện và ngắn gọn.
Bác xem hộ em nhé
Hàm LCD_dat4() chỉ nhận đối số là một ký tự. Bạn có thể viết thêm một hàm khác nhận đối số là một chuỗi, trong hàm đó bạn lần lượt lấy từ ký tự của chuỗi ra và dùng hàm LCD_dat4() để xuất ra LCD.

Ví dụ của tôi sử dụng chuỗi trong flash, vì nó là chuỗi hằng. Bạn hoàn toàn có thể thay chuỗi hằng đó bằng biến chuỗi (đã có bạn hỏi tôi về việc này, và tôi đã trả lời ở đây: http://www.picvietnam.com/forum/showthread.php?t=3053).

Thân,

tungtuantu
13-11-2008, 11:25 PM
em đã viết hàm xuất ra chuỗi giống hàm PutsXLCD của module XLCD, hàm như sau :

void LCD_PutChar( char *buffer)

{

while(*buffer != '\0')
{
LCD_dat4(*buffer); /* calling another function */
/* to write each char to the lcd module */
buffer++;
}
} /* end of function */

trong hàm main em viết LCD_PutChar(''DSPIC")
hoặc e khai báo như sau
char * buffer;
char mesg1[] = {'H','A','R','D','W','A','R','E','\0'};
buffer = mesg1;
LCD_PutChar(buffer);
Cả 2 cách trên thì chuỗi xuất ra trên LCD đều loạn cả lên.
Em thử dùng cách printf(LCD_dat4,"DSPIC") giống CCS mà ko được, mình có cách nào lợi dụng hàm printf ko bác

namqn
13-11-2008, 11:42 PM
em đã viết hàm xuất ra chuỗi giống hàm PutsXLCD của module XLCD, hàm như sau :

void LCD_PutChar( char *buffer)

{

while(*buffer != '\0')
{
LCD_dat4(*buffer); /* calling another function */
/* to write each char to the lcd module */
buffer++;
}
} /* end of function */

trong hàm main em viết LCD_PutChar(''DSPIC")
hoặc e khai báo như sau
char * buffer;
char mesg1[] = {'H','A','R','D','W','A','R','E','\0'};
buffer = mesg1;
LCD_PutChar(buffer);
Cả 2 cách trên thì chuỗi xuất ra trên LCD đều loạn cả lên.
Em thử dùng cách printf(LCD_dat4,"DSPIC") giống CCS mà ko được, mình có cách nào lợi dụng hàm printf ko bác
Bạn thử hàm này xem:
void LCD_PutStr(char *buffer)
{
unsigned int i = 0;
while (buffer[i] != '\0')
{
LCD_dat4(buffer[i]); /* calling another function */
/* to write each char to the lcd module */
i++;
//Nên delay một khoảng thời gian giữa các ký tự
//để LCD có thời gian đáp ứng với yêu cầu trước đó
}
} /* end of function */

Bạn nên tìm một tài liệu hướng dẫn lập trình C cơ bản để đọc.

Thân,

tungtuantu
14-11-2008, 11:47 AM
Em xin post code mà em giao tiếp với LCD kiểu 4 bit, với các chân được set tùy ý theo phần cứng, bổ xung thêm theo code của bác hàm :
lcd_putstr("string here"); //Xuat 1 ky tu hay 1 chuoi ky tu
lcd_gotoxy(int x, int y ); //Nhay den cot x, hang y
Để bạn nào mới học như em có thêm nguồn tham khảo
Em rất cám ơn bác namqn tận tình giúp đỡ em


; Nhung tap tin can thiet khac: p30F4011.gld, p30f4011.h *

; Phan cung: *
; LCD_EN = RC13 *
; LCD_RW = RB8 *
; LCD_RS = RB7 *
; LCD_D4 = RC14 *
; LCD_D5 = RE8 *
; LCD_D6 = RD1 *
; LCD_D7 = RD3 *
; Chuong trinh nay dung che do giao tiep 4-bit voi LCD, *

------------------------------------------------------------------------------*/
#include "p30f4011.h"

_FOSC(CSW_FSCM_OFF & FRC_PLL4); //Clock = 32 MHz
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)

#define ms_count 125 //So dem tuong ung voi 1 ms, cho timer 1


#define LCD_EN _LATC13 //Tin hieu Enable cho LCD, chan RE8
#define LCD_RW _LATB8 //Tin hieu Read/Write cho LCD, chan RD0
#define LCD_RS _LATB7 //Tin hieu Reset cho LCD, chan RD1

#define LCD_D4 _LATC14 //Cac tin hieu Data cho LCD, chan (D4..D7)
#define LCD_D5 _LATE8
#define LCD_D6 _LATD1
#define LCD_D7 _LATD3

#define TRIS_LCD_D4 _TRISC14 //Tristate cua cac tin hieu Data cho LCD
#define TRIS_LCD_D5 _TRISE8
#define TRIS_LCD_D6 _TRISD1
#define TRIS_LCD_D7 _TRISD3

#define LCD_clear 0x01 //Xoa man hinh LCD
#define LCD_home 0x02 //Tro ve dau dong
#define LCD_normal 0x06 //Che do nhap du lieu binh thuong
#define LCD_normal_s 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_off 0x08 //Tat man hinh
#define LCD_on 0x0C //Bat man hinh
#define LCD_on_crsr 0x0E //Bat man hinh va con tro
#define LCD_on_blink 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_4b2l 0x28 //Che do 2 dong, giao tiep 4 bit du lieu
#define LCD_homeL1 0x80 //Ve dau dong 1
#define LCD_homeL2 0xC0 //Ve dau dong 2
#define lcd_line_two 0x40

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void); //Khoi tao cac cong I/O
void Delay_ms(unsigned int); //Tao tre n ms
void Init_LCD(void); //Khoi tao LCD
void LCD_cmd4(unsigned char); //Xuat lenh ra LCD qua giao tiep 4-bit
void LCD_dat4(unsigned char); //Xuat du lieu ra LCD qua giao tiep 4-bit
void lcd_putstr(char *buffer); //Xuat 1 ky tu hay 1 chuoi ky tu
void lcd_gotoxy(int x, int y ); //Nhay den cot x, hang y


//------------------------------------------------------------------------------
//Chuong trinh chinh
void main()
{
_TRISE3 = 0;

Init_PORTS(); //Khoi tao cac cong I/O
Init_LCD(); //Khoi tao LCD
lcd_putstr("NGUYEN THE TUNG");
lcd_gotoxy(4,2);
lcd_putstr("DTD45-DH1");
while (1)
{
_LATE3=1;
Delay_ms(250); //Vong lap chinh
_LATE3=0;
Delay_ms(250);
}
}


//Chuong trinh con khoi tao cac cong I/O, de noi voi LED
//------------------------------------------------------------------------------
void Init_PORTS(void)
{
LCD_D4 = 0; //Xoa cac bit chot du lieu LCD
LCD_D5 = 0;
LCD_D6 = 0;
LCD_D7 = 0;

TRIS_LCD_D4 = 0; //Cac chan du lieu LCD la ngo ra
TRIS_LCD_D5 = 0;
TRIS_LCD_D6 = 0;
TRIS_LCD_D7 = 0;

LCD_EN = 0;
_TRISC13 = 0; //RE8 la ngo ra, noi vao Enable cua LCD
LCD_RW = 0;
_TRISB8 = 0; //RD0 la ngo ra, noi vao R/W cua LCD
LCD_RS = 0;
_TRISB7 = 0; //RD1 la ngo ra, noi vao Reset cua LCD
}

//Chuong trinh con delay bang timer 1, tre n ms
//TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
//------------------------------------------------------------------------------
void Delay_ms(unsigned int n)
{
TMR1 = 0; //Xoa so dem trong TMR1
T1CON = 0x0020; //Dung fcy lam clock, prescale = 1:64, tat Timer 1
PR1 = n*ms_count; //Dat nguong tran vao PR1
T1CONbits.TON = 1; //Bat timer 1
while (!_T1IF ); //Cho den khi het thoi gian cho
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CONbits.TON = 0; //Tat timer 1

}

//Chuong trinh con khoi tao module LCD
//------------------------------------------------------------------------------
void Init_LCD(void) {
LCD_cmd4(LCD_4b2l); //Dat che do giao tiep 4-bit, man hinh 2 dong
Delay_ms(1);
LCD_cmd4(LCD_off); //Tat man hinh
Delay_ms(1);
LCD_cmd4(LCD_normal); //Che do nhap du lieu binh thuong
Delay_ms(1);
LCD_cmd4(LCD_on); //Bat man hinh, hien con tro nhap nhay
Delay_ms(1);
LCD_cmd4(LCD_clear); //Xoa man hinh
Delay_ms(5);

}

//Chuong trinh con xuat lenh o che do 4 bit
//------------------------------------------------------------------------------
void LCD_cmd4(unsigned char cmd) {
unsigned temp1, i;
LCD_RW = 0;
LCD_RS = 0; //Dat che do xuat lenh
temp1 = cmd >> 4; //Lay 4 bit cao
LCD_D4 = temp1 & 1; //Xuat 4 bit cao
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp1 = cmd & 0x0F; //Lay 4 bit thap
LCD_D4 = temp1 & 1; //Xuat 4 bit thap
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh con xuat du lieu o che do 4 bit
//------------------------------------------------------------------------------
void LCD_dat4(unsigned char dat) {
unsigned temp2, i;
LCD_RW = 0;
LCD_RS = 1; //Dat che do xuat du lieu
temp2 = dat >> 4; //Lay 4 bit cao
LCD_D4 = temp2 & 1; //Xuat 4 bit cao
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp2 = dat & 0x0F; //Lay 4 bit thap
LCD_D4 = temp2 & 1; //Xuat 4 bit thap
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}
//Chuong trinh con xuat 1 ky tu hay 1 chuoi ky tu
//------------------------------------------------------------------------------
void lcd_putstr(char *buffer)
{

while(*buffer != '\0')
{
LCD_dat4(*buffer); /* calling another function */
/* to write each char to the lcd module */
buffer++;
Delay_ms(1);

}
}
//Chuong trinh con nhay den cot x, dong y
//------------------------------------------------------------------------------
void lcd_gotoxy(int x, int y)
{
int address;

if(y != 1) address = lcd_line_two;
else address=0;

address += x-1;
LCD_cmd4( 0x80 | address);
Delay_ms(1);
}

conglong
11-03-2009, 11:05 AM
Thầy Nam cho em hỏi: trong tutorial này thầy dung RE0->RE3 làm 4 chân data (D4->D7) của LCD , còn trong phần cứng của em , em dùng RE2 ->RE5 làm chân data cho LCD, vậy em phải làm sao để gi được dữ liệu cũng như lệnh cho LCD hả thầy , em đã thêm đoạn mã sau vào hàm " void LCD_cmd4(unsigned char cmd)" của thầy mà không được:

"#define LCD_LAT LATE //tin hieu Data cho LCD, chan RE2..RE5
#define LCD_TRIS TRISE //Tristate cua cac tin hieu Data
unsigned temp1,temp2,i;
LCD_RW_LAT = 0; //WRITE DATA TO LCD
LCD_RS_LAT = 0; //Dat che do xuat lenh
temp1 = LCD_LAT & 0xFFF0; //trang thai hien thoi cua LCD_LAT
temp2 = temp1 | (cmd >> 4);
LCD_LAT =(temp2<<2); //Xuat 4 bit cao ra RE5 toi RE2
LCD_EN_LAT = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN_LAT = 0; "

Mong thầy giup em
Em cảm ơn thầy!
Trân trọng !

namqn
11-03-2009, 05:57 PM
Thầy Nam cho em hỏi: trong tutorial này thầy dung RE0->RE3 làm 4 chân data (D4->D7) của LCD , còn trong phần cứng của em , em dùng RE2 ->RE5 làm chân data cho LCD, vậy em phải làm sao để gi được dữ liệu cũng như lệnh cho LCD hả thầy , em đã thêm đoạn mã sau vào hàm " void LCD_cmd4(unsigned char cmd)" của thầy mà không được:

"#define LCD_LAT LATE //tin hieu Data cho LCD, chan RE2..RE5
#define LCD_TRIS TRISE //Tristate cua cac tin hieu Data
unsigned temp1,temp2,i;
LCD_RW_LAT = 0; //WRITE DATA TO LCD
LCD_RS_LAT = 0; //Dat che do xuat lenh
temp1 = LCD_LAT & 0xFFF0; //trang thai hien thoi cua LCD_LAT
temp2 = temp1 | (cmd >> 4);
LCD_LAT =(temp2<<2); //Xuat 4 bit cao ra RE5 toi RE2
LCD_EN_LAT = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN_LAT = 0; "

Mong thầy giup em
Em cảm ơn thầy!
Trân trọng !
Trước hết, bạn phải đảm bảo là các chân RE2..RE5 là các ngõ ra, do đó cần điều chỉnh lại giá trị của LCD_TRIS trong hàm Init_PORTS() thành 0xFFC3.

Thứ hai, mặt nạ để đọc trạng thái hiện thời của LCD_LAT không còn là 0xFFF0 nữa, mà phải là 0xFFC3 (tức là phải dùng lệnh temp1 = LCD_LAT & 0xFFC3).

Thứ ba, xử lý xong dữ liệu cmd rồi mới OR với temp1 (tức là dùng temp2 = (cmd >> 4) << 2; rồi đến LCD_LAT = temp1 | temp2; ).

Tổng hợp điểm thứ hai và thứ ba, cần dùng các lệnh sau:
temp1 = LCD_LAT & 0xFFC3; //trang thai hien thoi cua LCD_LAT
temp2 = (cmd >> 4) << 2;
LCD_LAT = temp1 | temp2; //Xuat 4 bit cao ra RE5 toi RE2

Thân,

conglong
12-03-2009, 04:20 PM
Thây Nam cho em hoi câu nữa là em dung dsPic 30f2010 vậy thì dong lệnh khai báo không gian PSV có phải thay đổi địa chỉ không hả thầy ? nếu em để vậy thì khi biên dịch nó lại báo lỗi ! là không định địa chỉ như vậy được .
Em cảm ơn thầy nhiều !
Trân trọng !

thuyenld
12-03-2009, 04:55 PM
cho em hỏi hàm delay_ms(n) thì n max là bao nhiêu.
em đã thử với n>1000 thì thấy thời gian trễ lại nhỏ dần(ngược lại).

namqn
12-03-2009, 05:28 PM
Thây Nam cho em hoi câu nữa là em dung dsPic 30f2010 vậy thì dong lệnh khai báo không gian PSV có phải thay đổi địa chỉ không hả thầy ? nếu em để vậy thì khi biên dịch nó lại báo lỗi ! là không định địa chỉ như vậy được .
Em cảm ơn thầy nhiều !
Trân trọng !
Vị trí của bảng hằng số trong ROM phụ thuộc vào độ lớn của code chương trình (vì chương trình dịch sẽ đặt code chương trình chính, các chương trình con, và các chương trình xử lý ngắt ở trước bảng hằng số, nếu bạn theo cấu trúc chương trình ví dụ của tôi), chứ không phụ thuộc vào việc bạn dùng dsPIC nào (ở đây nói đến vị trí tương đối).

Một cách đơn giản để xử lý là bạn đặt bảng hằng số ở gần cuối bộ nhớ chương trình của dsPIC, bằng cách thay đổi địa chỉ trong phần address(). Chẳng hạn, với dsPIC30F2010 thì địa chỉ của từ nhớ cuối cùng trong flash là 0x1FFE, do đó bạn có thể dùng 0x1F00 cho bảng hằng số có dưới 128 phần tử.

Thân,

namqn
12-03-2009, 05:30 PM
cho em hỏi hàm delay_ms(n) thì n max là bao nhiêu.
em đã thử với n>1000 thì thấy thời gian trễ lại nhỏ dần(ngược lại).
Hàm delay_ms(n) dùng hằng số ms_count = 125 để nhân với n, và đặt kết quả vào thanh ghi PR1 (là một thanh ghi 16-bit). Do đó, giá trị lớn nhất của n là 65535/125 = 524 (phần nguyên). Nếu bạn dùng giá trị n lớn hơn 524 thì chỉ có 16 bit thấp nhất của kết quả được dùng để đặt vào PR1, dẫn đến hiện tượng mà bạn đã thấy.

Thân,

conglong
13-03-2009, 01:29 AM
Vị trí của bảng hằng số trong ROM phụ thuộc vào độ lớn của code chương trình (vì chương trình dịch sẽ đặt code chương trình chính, các chương trình con, và các chương trình xử lý ngắt ở trước bảng hằng số, nếu bạn theo cấu trúc chương trình ví dụ của tôi), chứ không phụ thuộc vào việc bạn dùng dsPIC nào (ở đây nói đến vị trí tương đối).

Một cách đơn giản để xử lý là bạn đặt bảng hằng số ở gần cuối bộ nhớ chương trình của dsPIC, bằng cách thay đổi địa chỉ trong phần address(). Chẳng hạn, với dsPIC30F2010 thì địa chỉ của từ nhớ cuối cùng trong flash là 0x1FFE, do đó bạn có thể dùng 0x1F00 cho bảng hằng số có dưới 128 phần tử.

Thân,
Dạ vâng . nó giờ ko báo lỗi chố đó nữa , mà lại báo lỗi ở hai hàng :
#define LCD_DAT _LATE
#define LCD_TRIS _TRISE
Nhưng nếu em thay hai hàng này bởi hai hang sau
#define LCD_DAT LATE
#define LCD_TRIS TRISE
thì không còn báo lỗi ở đó nữa (em đang dùng dsPIC30F2010) !
xin chỉ em với tại sao lại vậy , với lại nếu nạp chương trình này vào thì nó có chạy nhưng không chính xác , LCD không hiển thị những kí tự mình mong muốn.
Em cảm ơn thầy !
Trân trọng !.

namqn
13-03-2009, 04:18 AM
Dạ vâng . nó giờ ko báo lỗi chố đó nữa , mà lại báo lỗi ở hai hàng :
#define LCD_DAT _LATE
#define LCD_TRIS _TRISE
Nhưng nếu em thay hai hàng này bởi hai hang sau
#define LCD_DAT LATE
#define LCD_TRIS TRISE
thì không còn báo lỗi ở đó nữa (em đang dùng dsPIC30F2010) !
xin chỉ em với tại sao lại vậy , với lại nếu nạp chương trình này vào thì nó có chạy nhưng không chính xác , LCD không hiển thị những kí tự mình mong muốn.
Em cảm ơn thầy !
Trân trọng !.
Mã nguồn đi kèm với tutorial của tôi cũng không có dấu "_" (underscore). Không rõ vì lý do gì bạn lại có những ký tự đó. Trong tập tin .h của dsPIC tương ứng chỉ có các khai báo với tên thanh ghi không có dấu "_".

Việc LCD của bạn không hiển thị không chính xác thì phải xem bạn khởi tạo và điều khiển LCD ra sao (đến giờ bạn chỉ đưa lên có một đoạn code liên quan đến hàm LCD_cmd4() thôi). Trong tutorial, tôi có ghi chú về trường hợp LCD mới, cần được khởi tạo đầy đủ (ở trang 10, về việc thực hiện quy trình khởi tạo đầy đủ như được nêu trong datasheet của HD44780U). Đề nghị bạn xem lại và đối chiếu với code của bạn.

Thân,

conglong
13-03-2009, 12:40 PM
Hàm delay_ms(n) dùng hằng số ms_count = 125 để nhân với n, và đặt kết quả vào thanh ghi PR1 (là một thanh ghi 16-bit). Do đó, giá trị lớn nhất của n là 65535/125 = 524 (phần nguyên). Nếu bạn dùng giá trị n lớn hơn 524 thì chỉ có 16 bit thấp nhất của kết quả được dùng để đặt vào PR1, dẫn đến hiện tượng mà bạn đã thấy.

Thân,

Vậy thầy Nam cho em hỏi em muốn viết hàm delay có thể cho delay một khoảng thời gian >524 ms thì em phải làm sao hay là cũng dùng hàm đó nhưng gọi nhiều lần , vậy thì không pro chút nào đúng không thầy ,
em cảm ơn !
Trân trọng !

conglong
13-03-2009, 04:10 PM
Trong TUTO này , thầy có dùng kí tự "\0" hình như là để nhận biết kết thúc một chuỗi cần hiển thị phải không thầy ? Thầy có thể nói rõ chố này dùm em được không? có phải đây là quy định của lập trình C ? ngoài ra còn có cách nào khác nứa không thầy ?
Em cảm ơn !
Trân trọng !

namqn
13-03-2009, 05:20 PM
Vậy thầy Nam cho em hỏi em muốn viết hàm delay có thể cho delay một khoảng thời gian >524 ms thì em phải làm sao hay là cũng dùng hàm đó nhưng gọi nhiều lần , vậy thì không pro chút nào đúng không thầy ,
em cảm ơn !
Trân trọng !
Để làm trễ nhiều hơn nữa, bạn có thể cấu hình timer để sử dụng hệ số chia trước lớn hơn. Khi đó, số đếm tương ứng với 1 ms (ms_count) sẽ nhỏ hơn, và bạn sẽ có thể làm trễ với khoảng thời gian lớn hơn.

Việc làm trễ bằng cách gọi nhiều lần một hàm cũng không có gì là không pro.

Tuy nhiên, tôi viết các hàm làm trễ kiểu này chỉ cho mục đích làm trễ vài ms, chứ không dự định dùng nó để làm trễ vài giây, vì các hàm loại này sẽ block hoạt động của lõi xử lý trong vi điều khiển.

Thân,

namqn
13-03-2009, 05:26 PM
Trong TUTO này , thầy có dùng kí tự "\0" hình như là để nhận biết kết thúc một chuỗi cần hiển thị phải không thầy ? Thầy có thể nói rõ chố này dùm em được không? có phải đây là quy định của lập trình C ? ngoài ra còn có cách nào khác nứa không thầy ?
Em cảm ơn !
Trân trong !
Đúng là tôi dùng ký tự "\0" để đánh dấu điểm kết thúc của chuỗi ký tự. Đây không phải là quy định của C, nhưng là một trong những format chuẩn của C. Nếu chuỗi của bạn là các ký tự ASCII, format này được gọi là ASCIIZ (ASCII zero).

Bạn có thể dùng nhiều cách khác nhau để nhận biết điểm kết thúc của chuỗi ký tự. Chẳng hạn, bạn có thể dành ra một byte ở đầu chuỗi để theo dõi chiều dài thực của chuỗi (kiểu string của Pascal), hay có thể dùng một ký tự điều khiển như "\r" hay "\n" (kiểu kết thúc dòng lệnh của một số ngôn ngữ scripting).

Tôi chọn dùng ký tự "\0" vì tập lệnh của dsPIC có sẵn lệnh so sánh với 0, do đó việc hiện thực sẽ hiệu quả hơn.

Thân,

conglong
13-03-2009, 06:54 PM
Thầy Nam cho em hỏi: giả sử em đã có hàm hiện thị LCD là:
Void LCD_putstr(char *buffer)
Vậy em phải làm sao để hiển thị giá trị của một thanh ghi nào đó (ví dụ như thanh ghi PR1) lên LCD hả thầy?.
Em đã thử gọi như sau nhưng không được :

LCD_putstr(PR1) ;

Trong khi đó em gọi hàm này với đối số là chuối kí tự thì được.
Em cảm ơn thầy nhiều !
Trân trọng !

namqn
13-03-2009, 08:24 PM
Thầy Nam cho em hỏi: giả sử em đã có hàm hiện thị LCD là:
Void LCD_putstr(char *buffer)
Vậy em phải làm sao để hiển thị giá trị của một thanh ghi nào đó (ví dụ như thanh ghi PR1) lên LCD hả thầy?.
Em đã thử gọi như sau nhưng không được :

LCD_putstr(PR1) ;

Trong khi đó em gọi hàm này với đối số là chuối kí tự thì được.
Em cảm ơn thầy nhiều !
Trân trọng !
Thanh ghi PR1 là một thanh ghi 16-bit, và được trình biên dịch xem như một số có kiểu int. Do đó, bạn không thể dùng nó làm đối số cho hàm LCD_putstr() của bạn.

Để hiển thị giá trị của thanh ghi này lên LCD, bạn cần chuyển giá trị int của nó thành một chuỗi ký tự. Với MPLAB C30, bạn có thể dùng hàm sprintf() để làm việc này. Ví dụ cụ thể với chuỗi buffer của bạn:
sprintf(buffer, "%d", PR1);
Sau lệnh này, buffer sẽ chứa chuỗi ký tự biểu diễn giá trị của PR1 trong hệ thập phân. Phần format ("%d") giống như của printf(), bạn tham khảo thêm về các option định dạng khác.

Thân,

silvadk2
16-03-2009, 09:34 AM
Anh nam ơi, có một đoạn code thế này, em đọc nhưng chưa hiểu hết được, anh có thể giải thích cho em kỹ hơn không ?

// Function: LCD_CMD
// Description: Send command to LCD
// Input: Command code
// Output: None
//
//************************************************** *************************//
void LCD_CMD(unsigned char CMD)
{
// LCDdelayms(1);
unsigned char TempData;
LCD_RS = 0; //Dat che do xuat lenh
TempData = LCD_DATA & 0xFFF0; //Lay trang thai hien thoi cua LCD_DATA
LCD_DATA = TempData | (CMD>>4); //Xuat 4 bit cao
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
TempData = LCD_DATA & 0xFFF0; //Lay trang thai hien thoi cua LCD_DATA
LCD_DATA = TempData| (CMD & 0x0F); //Xuat 4 bit thap
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
}
//************************* End of LCD_CMD *********************************//


//************************************************** *************************//
//
// Function: LCD_DATA
// Description: Send data to LCD
// Input: Command code
// Output: None
//
//************************************************** *************************//
void LCD_DAT(unsigned char DATA)
{
unsigned char TempData;
// LCDdelayms(1);
LCD_RS = 1; //Dat che do xuat du lieu
TempData = LCD_DATA & 0xFFF0; //Lay trang thai hien thoi cua LCD_DATA
LCD_DATA = TempData | (DATA >> 4); //Xuat 4 bit cao
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
TempData = LCD_DATA & 0xFFF0; //Lay trang thai hien thoi cua LCD_DATA
LCD_DATA = TempData | (DATA & 0x0F); //Xuat 4 bit thap
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
}

Cám ơn anh nhiều !

mtuankct
16-03-2009, 10:39 AM
Bạn chưa hiểu chỗ nào? Theo mình trong chương trình này có 2 chương trình con, cái thứ nhất

void LCD_CMD(unsigned char CMD)
{
// LCDdelayms(1);
unsigned char TempData;
LCD_RS = 0; //Dat che do xuat lenh
TempData = LCD_DATA & 0xFFF0; //Lay trang thai hien thoi cua LCD_DATA
LCD_DATA = TempData | (CMD>>4); //Xuat 4 bit cao
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
TempData = LCD_DATA & 0xFFF0; //Lay trang thai hien thoi cua LCD_DATA
LCD_DATA = TempData| (CMD & 0x0F); //Xuat 4 bit thap
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
}

dùng để gửi một lệnh lên LCD, mã lệnh được truyền vào bằng tham số CMD, LCD hoạt động ở chế độ 4 bit
Dòng LCD_RS = 0; là đặt chế độ xuất lệnh
Dòng TempData = LCD_DATA & 0xFFF0; là đọc trạng thái của LCD và đồng thời xóa 4 bít thấp của trạng thái đọc về bằng phép &
Dòng LCD_DATA = TempData | (CMD>>4); là xuất 4 bít cao của lệnh bằng cách sử dụng lệnh OR bit và lệnh dịch bít để thu được 4 bít cao vào vị trí của 4 bít thấp trong TempData đã xóa ở lệnh trước
Hàm ShortDelay(); là để tạo thời gian trễ đảm bảo đủ thời gian đáp ứng của LCD
các lệnh và hàm còn lại cũng tuơng tự thế thôi

silvadk2
16-03-2009, 01:35 PM
cảm ơn bạn tuấn, các dòng lệnh thì mình cũng hiểu tàm tạm, nhưng, sử dụng chương trình con này thì mình chưa rõ lắm, ví dụ :

LCD_CMD(LCD_4B2L); //Dat che do giao tiep 4-bit, man hinh 2 dong

Thì nó xẽ hoạt động như thế nào?
Thank bạn nha!

mtuankct
16-03-2009, 04:33 PM
Lệnh LCD_CMD(LCD_4B2L); chỉ là một lệnh gọi hàm mà tham số vào là LCD_4B2L, nghĩa là send đến LCD mã lệnh LCD_4B2L đây là một mã lệnh đã được định nghĩa trước bằng lệnh #define LCD_4B2L gia_tri; còn giá trị này bằng bao nhiêu thì bạn phải đọc lại phần LCD

silvadk2
16-03-2009, 04:36 PM
uh, mình hiểu rồi, cảm ơn bạn nha !

silvadk2
25-03-2009, 10:14 PM
:(. Hic, anh nam có thể viết cho em chương trình con xuất lệnh và dữ liệu ở chế độ 8bit bằng C30 không ạ.

namqn
25-03-2009, 10:17 PM
:(. Hic, anh nam có thể viết cho em chương trình con xuất lệnh và dữ liệu ở chế độ 8bit bằng C30 không ạ.
Việc này còn đơn giản hơn so với chế độ 4-bit nữa, bạn thử suy nghĩ một chút xem. Tôi đảm bảo có nhiều bạn thành viên trên diễn đàn này có thể giúp bạn, không nhất thiết phải là tôi đâu.

Thân,

silvadk2
25-03-2009, 10:19 PM
phần cứng của em là nối RB0->RB7 với D0-D7. còn RS,RW, và E nối với RF6,RF3, và RF2.

silvadk2
25-03-2009, 10:29 PM
void LCD_CMD(unsigned char CMD)
{
// LCDdelayms(1);
LCD_RW=0;
LCD_RS = 0;
LCD_DATA = CMD;
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
}
Em nghĩ là như thế này, có đúng ko bác !

namqn
25-03-2009, 11:31 PM
void LCD_CMD(unsigned char CMD)
{
// LCDdelayms(1);
LCD_RW=0;
LCD_RS = 0;
LCD_DATA = CMD;
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable
}
Em nghĩ là như thế này, có đúng ko bác !
Code của bạn là ổn rồi. Bạn nhớ thay đổi các phần #define cho các chân RW, RS, EN, và 8-bit dữ liệu cho phù hợp với phần cứng của bạn, và đảm bảo là các bit TRIS tương ứng với 8-bit dữ liệu được thiết lập một cách thích hợp.

Thân,

silvadk2
26-03-2009, 12:44 AM
Hic, đây là code của em, biên dịch thì ko lỗi, nhưng nạp vào thì chẳng thấy LCD viết gì anh ạ, chán thế .

#include <p30f4011.h>
#include <string.h>

_FOSC(CSW_FSCM_OFF & HS);
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_ON & BORV_27);
_FGS(CODE_PROT_OFF);

#define LCD_EN LATFbits.LATF2 //Tin hieu Enable cho LCD, chan RF2
#define LCD_RS LATFbits.LATF6 //Tin hieu Reset cho LCD, chan RF6
#define LCD_RW LATFbits.LATF3 //Tin hieu doc ghi cho LCD, chan RF3
#define RW_TRIS TRISFbits.TRISF3
#define RS_TRIS TRISFbits.TRISF6
#define E_TRIS TRISFbits.TRISF2
#define LCD_PORTB PORTB
#define LCD_DATA LATB //Cac tin hieu Data cho LCD
#define LCD_TRIS TRISB //Tristate cua cac tin hieu Data cho LCD

#define LCD_CLEAR 0x01 //Xoa man hinh LCD
#define LCD_HOME 0x02 //Tro ve dau dong
#define LCD_NORMAL 0x06 //Che do nhap du lieu binh thuong
#define LCD_NORMAL_S 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_OFF 0x08 //Tat man hinh
#define LCD_ON 0x0C //Bat man hinh
#define LCD_ON_CRSR 0x0E //Bat man hinh va con tro
#define LCD_ON_BLINK 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_8B2L 0x38 //Che do 2 dong, giao tiep 8 bit du lieu
#define LCD_HOMEL1 0x80 //Ve dau dong 1
#define LCD_HOMEL2 0xC0 //Ve dau dong 2

#define ShortDelay() {Nop() Nop() Nop() Nop() Nop() Nop() Nop() Nop() Nop()}
//************************************************** *************************//


//************************************************** *************************//
//
// Function: LCDdelayms
// Description: LCDdelayms for LCD
// Input: Number of ms
// Output: None
//
//************************************************** *************************//
void LCDdelayms(unsigned int ms)
{
#define FCY 2500*4
unsigned int i=0;
while(ms--){while(++i<FCY/7); i=0;}
}
//*************************** END OF LCDDELAYMS ****************************//

void LCD_CMD(unsigned char CMD)
{

LCD_RW=0;
LCD_RS = 0;
LCD_DATA = CMD;
LCD_EN = 1; ShortDelay(); LCD_EN = 0;

}
//************************* End of LCD_CMD *********************************//

void LCD_DAT(unsigned char DATA)
{
LCD_RW=0;
LCD_RS = 1;
LCD_DATA = DATA;
LCD_EN = 1; ShortDelay(); LCD_EN = 0; //Xung Enable

}
//****************************** END OF LCD_DATA ****************************//



void InitLCD(void)
{
LCD_CMD(LCD_8B2L); //Dat che do giao tiep 8-bit, man hinh 2 dong
LCDdelayms(1);
LCD_CMD(LCD_8B2L); //Dat che do giao tiep 8-bit, man hinh 2 dong
LCDdelayms(1);
LCD_CMD(LCD_8B2L); //Dat che do giao tiep 8-bit, man hinh 2 dong
LCDdelayms(1);
LCD_CMD(LCD_OFF); //Tat man hinh
LCDdelayms(1);
LCD_CMD(LCD_CLEAR); //Xoa man hinh
LCDdelayms(1);
LCD_CMD(LCD_ON); //Bat man hinh
LCDdelayms(1);
LCD_CMD(LCD_NORMAL); //Che do nhap lieu binh thuong
//Cursor move Increment, Not to shift the display
LCDdelayms(1);
LCD_CMD(LCD_CLEAR); //Xoa man hinh
LCDdelayms(5);
}
//************************** END OF InitLCD *********************************//

void LCD_PutChar(unsigned char character)
{

LCD_DAT(character);
LCDdelayms(1);
}
//************************** END of LCD_PutChar *****************************//

void LCD_WriteString(const char *str)
{
// LCDdelayms(1);
char ps;
ps = *str;
while(ps>0)
{
str++;
if (ps==0) break;
LCDdelayms(1);
LCD_DAT(ps);
ps = *str;
}
}
//*********************** END OF LCD_Writestring ****************************//



void LCD_Gotoxy(char x, char y)
{
char tg;
LCDdelayms(5);
switch (y)
{
case 1:tg = 0x80+x;
break;
case 2:tg = 0xC0+x;
break;
}
LCD_CMD(tg);
}
//************************* END OF LCD_Gotoxy *******************************//

void LCD_Clear(void)
{
LCD_CMD(LCD_CLEAR);
}

void SystemInit(void)
{
//Init IO
TRISB = TRISB & 0xFF00; //RB0..RB7 Output.
TRISFbits.TRISF6 = 0;
TRISFbits.TRISF2 = 0;
TRISFbits.TRISF3 = 0;
LATB = 0xFF00;
LATFbits.LATF6 = 0;
LATFbits.LATF2 = 0;
LATFbits.LATF3 = 0;
//InitLCD
InitLCD();
}
//******************************* End of SystemInit *************************//

int main(void)
{
SystemInit();
LCD_Gotoxy(1,1); //Nhay den vi tri cot 1, dong 1.
LCD_WriteString("picvietnam");
LCDdelayms(10);
LCD_Gotoxy(3,2); //Nhay den vi tri cot 3, dong 2.
LCD_WriteString("dspic");

while(1); //Dung chuong trinh.
}
//********************************* End of Main *****************************//

namqn
26-03-2009, 01:27 AM
Chắc gì hàm LCD_WriteString() của bạn chạy đúng ý đồ (có chắc là bạn thay đổi được giá trị của tham số str hay không). Sao bạn không thử hàm lcd_putstr() của bạn tungtuantu ở trang 2 của luồng này (code đó đã thử nghiệm rồi).

Bạn nên thử xuất 1 ký tự duy nhất ra vị trí hiện tại trước, rồi thử di chuyển con trỏ, sau đó thử xuất 1 chuỗi ký tự với một hàm đáng tin cậy.

Các chú thích của bạn khi gọi LCD_gotoxy() cũng không chính xác đâu, cột 1 ứng với x = 0 đấy.

Thân,

silvadk2
26-03-2009, 02:20 AM
hic, em đã thử với cả hàm lcd_putstr() rồi mà ko được. Với lại, cái hàm LCD_WriteString() em đã dùng ở chế độ 4 bit, chạy ngon mà. Có khi nào do phần cứng không bác nhỉ .

namqn
26-03-2009, 05:16 AM
hic, em đã thử với cả hàm lcd_putstr() rồi mà ko được. Với lại, cái hàm LCD_WriteString() em đã dùng ở chế độ 4 bit, chạy ngon mà. Có khi nào do phần cứng không bác nhỉ .
Vậy sơ đồ phần cứng của bạn ra sao? Tôi nghĩ rằng bạn đã hiện thực thành công ở chế độ 4 bit thì module LCD và mạch ứng dụng PIC của bạn đã ổn rồi. Tuy nhiên, nếu bạn muốn chúng tôi xem lại mạch nguyên lý cho bạn thì bạn cứ post sơ đồ lên.

Thân,

namqn
26-03-2009, 05:35 AM
hic, em đã thử với cả hàm lcd_putstr() rồi mà ko được. Với lại, cái hàm LCD_WriteString() em đã dùng ở chế độ 4 bit, chạy ngon mà. Có khi nào do phần cứng không bác nhỉ .
Tôi vừa xem lại code của bạn, để dùng các chân RB0..RB7 như ngõ ra digital thì bạn phải bật 8 bit thấp của thanh ghi ADPCFG lên '1' (ADPCFG = ADPCFG | 0x00FF chẳng hạn) trước khi dùng các chân này cho giao tiếp với LCD.

Thân,

silvadk2
26-03-2009, 12:05 PM
hic, em thử rồi mà vẫn ko được là sao nhỉ ?

silvadk2
26-03-2009, 01:08 PM
Oa oa anh ơi, được rồi . Ha ha, thank anh nhiều lắm . May quá, em sửa mãi mà ko được, giờ mới được.

silvadk2
27-03-2009, 11:32 AM
à, em còn 1 vấn đề là, em ghi giá trị đọc được từ ADC vào biến ADCvalue, sau đó, em dùng hàm chuyển đổi kiểu :
sprintf(Nhietdo, "%d",ADCvalue );
rồi dùng lệnh lcd_putstr(Nhietdo) (Hàm của anh Nam viết ở trang 2) để hiển thị lên LCD mà ko thấy gì cả. Anh xem hộ em mới

namqn
27-03-2009, 05:13 PM
à, em còn 1 vấn đề là, em ghi giá trị đọc được từ ADC vào biến ADCvalue, sau đó, em dùng hàm chuyển đổi kiểu :
sprintf(Nhietdo, "%d",ADCvalue );
rồi dùng lệnh lcd_putstr(Nhietdo) (Hàm của anh Nam viết ở trang 2) để hiển thị lên LCD mà ko thấy gì cả. Anh xem hộ em mới
Bạn khai báo Nhietdo như thế nào?

Thân,

ltpbkis
31-03-2009, 05:16 PM
Em code lại chương trình của bác Tungtuantu, thay RW-RB6; RS-RB7; EN-RC15; RD0-DB4; RD1-DB5; RD2-DB6; RD3-DB7
Em sử dụng thạch anh 7.3728, lCD của em la C1602a, chân của DSpic em nối trực tiếp với chân của LCD.
Em thay đổi chương trình lại như sau. Nhưng khi nạp vào thì mạch ko chạy.
Các bác xem dùm em với. Em mới bước chân vào nghề....
Em có làm gì sai ko các bác??????????


#include "p30f4011.h"

_FOSC(CSW_FSCM_OFF & FRC_PLL16);
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)

#define ms_count 125 //So dem tuong ung voi 1 ms, cho timer 1


#define LCD_EN _LATC15
#define LCD_RW _LATB6
#define LCD_RS _LATB7

#define LCD_D4 _LATD0 //Cac tin hieu Data cho LCD, chan (D4..D7)
#define LCD_D5 _LATD1
#define LCD_D6 _LATD2
#define LCD_D7 _LATD3

#define TRIS_LCD_D4 _TRISD0 //Tristate cua cac tin hieu Data cho LCD
#define TRIS_LCD_D5 _TRISD1
#define TRIS_LCD_D6 _TRISD2
#define TRIS_LCD_D7 _TRISD3

#define LCD_clear 0x01 //Xoa man hinh LCD
#define LCD_home 0x02 //Tro ve dau dong
#define LCD_normal 0x06 //Che do nhap du lieu binh thuong
#define LCD_normal_s 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_off 0x08 //Tat man hinh
#define LCD_on 0x0C //Bat man hinh
#define LCD_on_crsr 0x0E //Bat man hinh va con tro
#define LCD_on_blink 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_4b2l 0x28 //Che do 2 dong, giao tiep 4 bit du lieu
#define LCD_homeL1 0x80 //Ve dau dong 1
#define LCD_homeL2 0xC0 //Ve dau dong 2
#define lcd_line_two 0x40

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void); //Khoi tao cac cong I/O
void Delay_ms(unsigned int); //Tao tre n ms
void Init_LCD(void); //Khoi tao LCD
void LCD_cmd4(unsigned char); //Xuat lenh ra LCD qua giao tiep 4-bit
void LCD_dat4(unsigned char); //Xuat du lieu ra LCD qua giao tiep 4-bit
void lcd_putstr(char *buffer); //Xuat 1 ky tu hay 1 chuoi ky tu
void lcd_gotoxy(int x, int y ); //Nhay den cot x, hang y


//------------------------------------------------------------------------------
//Chuong trinh chinh
void main()
{
_TRISE3 = 0;

Init_PORTS(); //Khoi tao cac cong I/O
Init_LCD(); //Khoi tao LCD
lcd_putstr("NGUYEN THE TUNG");
lcd_gotoxy(4,2);
lcd_putstr("DTD45-DH1");
while (1)
{
_LATE3=1;
Delay_ms(250); //Vong lap chinh
_LATE3=0;
Delay_ms(250);
}
}


//Chuong trinh con khoi tao cac cong I/O, de noi voi LED
//------------------------------------------------------------------------------
void Init_PORTS(void)
{
LCD_D4 = 0; //Xoa cac bit chot du lieu LCD
LCD_D5 = 0;
LCD_D6 = 0;
LCD_D7 = 0;

TRIS_LCD_D4 = 0; //Cac chan du lieu LCD la ngo ra
TRIS_LCD_D5 = 0;
TRIS_LCD_D6 = 0;
TRIS_LCD_D7 = 0;

LCD_EN = 0;
_TRISC15 = 0; //RE8 la ngo ra, noi vao Enable cua LCD
LCD_RW = 0;
_TRISB6 = 0; //RD0 la ngo ra, noi vao R/W cua LCD
LCD_RS = 0;
_TRISB7 = 0; //RD1 la ngo ra, noi vao Reset cua LCD
}

//Chuong trinh con delay bang timer 1, tre n ms
//TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
//------------------------------------------------------------------------------
void Delay_ms(unsigned int n)
{
TMR1 = 0; //Xoa so dem trong TMR1
T1CON = 0x0020; //Dung fcy lam clock, prescale = 1:64, tat Timer 1
PR1 = n*ms_count; //Dat nguong tran vao PR1
T1CONbits.TON = 1; //Bat timer 1
while (!_T1IF ); //Cho den khi het thoi gian cho
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CONbits.TON = 0; //Tat timer 1

}

//Chuong trinh con khoi tao module LCD
//------------------------------------------------------------------------------
void Init_LCD(void) {
LCD_cmd4(LCD_4b2l); //Dat che do giao tiep 4-bit, man hinh 2 dong
Delay_ms(1);
LCD_cmd4(LCD_off); //Tat man hinh
Delay_ms(1);
LCD_cmd4(LCD_normal); //Che do nhap du lieu binh thuong
Delay_ms(1);
LCD_cmd4(LCD_on); //Bat man hinh, hien con tro nhap nhay
Delay_ms(1);
LCD_cmd4(LCD_clear); //Xoa man hinh
Delay_ms(5);

}

//Chuong trinh con xuat lenh o che do 4 bit
//------------------------------------------------------------------------------
void LCD_cmd4(unsigned char cmd) {
unsigned temp1, i;
LCD_RW = 0;
LCD_RS = 0; //Dat che do xuat lenh
temp1 = cmd >> 4; //Lay 4 bit cao
LCD_D4 = temp1 & 1; //Xuat 4 bit cao
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp1 = cmd & 0x0F; //Lay 4 bit thap
LCD_D4 = temp1 & 1; //Xuat 4 bit thap
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh con xuat du lieu o che do 4 bit
//------------------------------------------------------------------------------
void LCD_dat4(unsigned char dat) {
unsigned temp2, i;
LCD_RW = 0;
LCD_RS = 1; //Dat che do xuat du lieu
temp2 = dat >> 4; //Lay 4 bit cao
LCD_D4 = temp2 & 1; //Xuat 4 bit cao
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp2 = dat & 0x0F; //Lay 4 bit thap
LCD_D4 = temp2 & 1; //Xuat 4 bit thap
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}
//Chuong trinh con xuat 1 ky tu hay 1 chuoi ky tu
//------------------------------------------------------------------------------
void lcd_putstr(char *buffer)
{

while(*buffer != '\0')
{
LCD_dat4(*buffer); /* calling another function */
/* to write each char to the lcd module */
buffer++;
Delay_ms(1);

}
}
//Chuong trinh con nhay den cot x, dong y
//------------------------------------------------------------------------------
void lcd_gotoxy(int x, int y)
{
int address;

if(y != 1) address = lcd_line_two;
else address=0;

address += x-1;
LCD_cmd4( 0x80 | address);
Delay_ms(1);
}

namqn
31-03-2009, 05:41 PM
Em code lại chương trình của bác Tungtuantu, thay RW-RB6; RS-RB7; EN-RC15; RD0-DB4; RD1-DB5; RD2-DB6; RD3-DB7
Em sử dụng thạch anh 7.3728, lCD của em la C1602a, chân của DSpic em nối trực tiếp với chân của LCD.
Em thay đổi chương trình lại như sau. Nhưng khi nạp vào thì mạch ko chạy.
Các bác xem dùm em với. Em mới bước chân vào nghề....
Em có làm gì sai ko các bác??????????
...
Bạn tungtuantu dùng PLL x4, còn bạn dùng PLL x16, do đó hằng số ms_count cần điều chỉnh lại hoặc cấu hình lại Timer 1, nếu không thì thời gian delay sẽ không phải là 1 ms với số đếm bằng ms_count. Quan trọng hơn, các đoạn code để tạo ra xung Enable rộng 1 us sẽ hẹp hơn nhiều, chỉ còn khoảng 270 ns thôi (nếu trước đó nó chính xác là 1 us), do đó có thể LCD không hiểu được lệnh và dữ liệu truyền từ dsPIC. Bạn cần điều chỉnh lại các đoạn code này.

Thân,

ltpbkis
02-04-2009, 08:51 AM
Cảm ơn anh Nam nhiều!Nhờ Sự trả lời nhiệt tình và sáng suốt của anh em đã sữa lại và đã chạy được.EM nhận thấy là mạch mình chạy được từ lần test trước nhưng em không điều chỉnh cái biến trở (bạcklight) nên ko nhìn thấy chữ.Hii.Một kinh nghiệm đáng nhớ.Trả giá bằng 1 ngày test.he he!
Giờ em thay đổi phần cứng là con thạch anh 20KHZ thì có phải thay đổi chương trình của bác Tungtuantu không nhỉ?
Muốn kiểm tra LCD có hoạt động bình thường mình có cách nào kiểm tra sơ bộ mà ko cần chạy chương trình để test không nhỉ?
Cảm ơn bác nhiều!

conglong
07-04-2009, 09:32 AM
Cảm ơn anh Nam nhiều!Nhờ Sự trả lời nhiệt tình và sáng suốt của anh em đã sữa lại và đã chạy được.EM nhận thấy là mạch mình chạy được từ lần test trước nhưng em không điều chỉnh cái biến trở (bạcklight) nên ko nhìn thấy chữ.Hii.Một kinh nghiệm đáng nhớ.Trả giá bằng 1 ngày test.he he!
Giờ em thay đổi phần cứng là con thạch anh 20KHZ thì có phải thay đổi chương trình của bác Tungtuantu không nhỉ?
Muốn kiểm tra LCD có hoạt động bình thường mình có cách nào kiểm tra sơ bộ mà ko cần chạy chương trình để test không nhỉ?
Cảm ơn bác nhiều!
Nếu bạn dùng thach anh ngoài 20Khz (??? hình như bạn định nói là 20Mhz ? chứ mình chư thấy ai dùng 20Khz cả !), và cấu hình dùng dao động thạch anh :
_FOSC(CSW_FSCM_OFF & XT_PLL16)
thì bạn không phải thay đổi gì cả vì khi này 20Khz nhỏ hơn rất nhiều so với 8Mhz của bộ dao động trong nên Tcy lúc này sẽ rất lớn , mà vẫn đề ở đây là thời gian delay giữa các câu lênh LCD, LCD chỉ yêu cầu ngưỡng thời gian này là ngưỡng MIN chứ không yêu cầu ngưỡng Max.(tham khảo thêm datasheet cảu LCD để biết về thời gian này)
Còn nếu bạn dùng 20Mhz thì phải thay đổi lại là:
_FOSC(CSW_FSCM_OFF & XT)
Trân trọng !

ltpbkis
07-04-2009, 09:43 PM
Nếu bạn dùng thach anh ngoài 20Khz (??? hình như bạn định nói là 20Mhz ? chứ mình chư thấy ai dùng 20Khz cả !), và cấu hình dùng dao động thạch anh :
_FOSC(CSW_FSCM_OFF & XT_PLL16)
thì bạn không phải thay đổi gì cả vì khi này 20Khz nhỏ hơn rất nhiều so với 8Mhz của bộ dao động trong nên Tcy lúc này sẽ rất lớn , mà vẫn đề ở đây là thời gian delay giữa các câu lênh LCD, LCD chỉ yêu cầu ngưỡng thời gian này là ngưỡng MIN chứ không yêu cầu ngưỡng Max.(tham khảo thêm datasheet cảu LCD để biết về thời gian này)
Còn nếu bạn dùng 20Mhz thì phải thay đổi lại là:
_FOSC(CSW_FSCM_OFF & XT)
Trân trọng !
Cảm ơn anh! Đúng là em nhầm giá trị thạch anh.Anh làm thực nhiều nên kinh nghiệm quá nhận biết được giá trị thạch anh trong khoảng nào. Tiện thể anh cho em hỏi sơ đồ nguyên lý để mở van (em chỉ điều khiển 1 con IRF540 mà em tìm ứng dụng toàn thấy điều khiển theo cặp mosfet dùng mấy con IR21xxx) khi dùng khối PWM để thay đổi thời gian đóng/mở van! ("sơ đồ mạch liên kết IRF540 với dspic!)
Mong được anh góp ý sớm!
Cảm ơn các anh!

truongqt
09-04-2009, 01:45 PM
Cảm ơn anh Nam nhiều!Nhờ Sự trả lời nhiệt tình và sáng suốt của anh em đã sữa lại và đã chạy được.EM nhận thấy là mạch mình chạy được từ lần test trước nhưng em không điều chỉnh cái biến trở (bạcklight) nên ko nhìn thấy chữ.Hii.Một kinh nghiệm đáng nhớ.Trả giá bằng 1 ngày test.he he!
Giờ em thay đổi phần cứng là con thạch anh 20KHZ thì có phải thay đổi chương trình của bác Tungtuantu không nhỉ?
Muốn kiểm tra LCD có hoạt động bình thường mình có cách nào kiểm tra sơ bộ mà ko cần chạy chương trình để test không nhỉ?
Cảm ơn bác nhiều!

Chào bạn. bạn có thể cho mình xin bài mà bạn đã sửa lại chạy được đó, để mình tham khảo, vì mình mới bắt đầu làm quen LCD, bạn nha. Thanks bạn nhìu. Email của mình: nguyenvantruongqt@gmail.com

ltpbkis
10-04-2009, 08:25 AM
Chào bạn. bạn có thể cho mình xin bài mà bạn đã sửa lại chạy được đó, để mình tham khảo, vì mình mới bắt đầu làm quen LCD, bạn nha. Thanks bạn nhìu. Email của mình: nguyenvantruongqt@gmail.com

Gửi mail cho cậu rồi.Nhận được chưa nhỉ?

thuyenld
10-04-2009, 10:27 AM
cho em hỏi :
em làm mạch LCD nhưng đi dây nhầm nối 4 chân data của LCD : DB0...DB3 thì có chạy được ko?(theo tutorial thì là DB4...DB7)
Nếu được thì code phải sửa như nào?
em cảm ơn.

namqn
10-04-2009, 04:53 PM
cho em hỏi :
em làm mạch LCD nhưng đi dây nhầm nối 4 chân data của LCD : DB0...DB3 thì có chạy được ko?(theo tutorial thì là DB4...DB7)
Nếu được thì code phải sửa như nào?
em cảm ơn.
Chip điều khiển của module LCD chỉ dùng các chân DB4..DB7 cho chế độ 4 bit, do đó bạn phải sửa lại phần cứng, không còn cách nào khác.

Thân,

ltpbkis
11-04-2009, 09:55 AM
Các bác cho em hỏi thêm nhé!
Em muốn hiển thị giá trị của đầu vào ADC ra LCd thi lam thế nào nhỉ? Giá trị của ADC được lưu ở ADCBUF, nhưng giá trị đó là dạng số nguyên. Khi muốn hiện thị dạng số thực ra LCD thì làm thế nào? Mình có thể chuyển đổi kiểu dữ liệu từ số nguyến sang dạng khác được ko?
Mong sớm nhận được hồi âm của các bác.

namqn
11-04-2009, 05:24 PM
Các bác cho em hỏi thêm nhé!
Em muốn hiển thị giá trị của đầu vào ADC ra LCd thi lam thế nào nhỉ? Giá trị của ADC được lưu ở ADCBUF, nhưng giá trị đó là dạng số nguyên. Khi muốn hiện thị dạng số thực ra LCD thì làm thế nào? Mình có thể chuyển đổi kiểu dữ liệu từ số nguyến sang dạng khác được ko?
Mong sớm nhận được hồi âm của các bác.
Giả sử điện áp tham chiếu (reference voltage) của bạn là 5 V, và bạn đang dùng ADC 10-bit, giá trị nguyên x mà bạn đọc vào sẽ tương ứng với giá trị thực x*5/1024 V. Bạn dùng công thức này để tính ra giá trị thực. Sau đó dùng hàm sprintf() để chuyển giá trị thực đó thành một chuỗi ký tự biểu diễn cho số thực tương ứng, rồi xuất chuỗi ký tự đó đến LCD để hiển thị.

Thân,

ltpbkis
13-04-2009, 04:51 PM
Em đã thử nhưng không thành công. Bác có thể nói cụ thể hơn không nhỉ?
Em dùng lệnh sprintf nhưng trình biên dịch báo lỗi. Có cách nào khác để chuyển dữ liệu từ float sang chuỗi ký tự không bác?

namqn
13-04-2009, 05:15 PM
Em đã thử nhưng không thành công. Bác có thể nói cụ thể hơn không nhỉ?
Em dùng lệnh sprintf nhưng trình biên dịch báo lỗi. Có cách nào khác để chuyển dữ liệu từ float sang chuỗi ký tự không bác?
Bạn post lệnh đã dùng và thông báo lỗi. Hàm sprintf() chắc chắn làm được việc mà bạn muốn làm.

Nếu bạn không nắm rõ cú pháp của hàm, hãy đọc tài liệu "16-bit Language Tools Libraries" (số hiệu tài liệu là DS51456), mục 2.13.

Thân,

ltpbkis
14-04-2009, 04:39 PM
Bác xem dùm em code của em sai đâu. Em mới học, chẳng biết xử lý thế nào cả.
Cảm ơn bác đã bỏ thời gian giúp đỡ em !

#include "p30f4011.h"
#include "stdio.h"
_FOSC(CSW_FSCM_OFF & FRC_PLL4); //Clock = 32 MHz
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);
#define ms_count 125
#define LCD_EN _LATC13 //Tin hieu Enable cho LCD, chan RE8
#define LCD_RW _LATB6 //Tin hieu Read/Write cho LCD, chan RD0
#define LCD_RS _LATB7 //Tin hieu Reset cho LCD, chan RD1

#define LCD_D4 _LATD0 //Cac tin hieu Data cho LCD, chan (D4..D7)
#define LCD_D5 _LATD1
#define LCD_D6 _LATD2
#define LCD_D7 _LATD3

#define TRIS_LCD_D4 _TRISD0 //Tristate cua cac tin hieu Data cho LCD
#define TRIS_LCD_D5 _TRISD1
#define TRIS_LCD_D6 _TRISD2
#define TRIS_LCD_D7 _TRISD3
#define SW_DAT PORTE //Cac tin hieu Data cho switch, chan RB0..RB4 (S1..S5)
#define SW_TRIS TRISE //Tristate cua cac tin hieu Data cho switch


#define LCD_clear 0x01 //Xoa man hinh LCD
#define LCD_home 0x02 //Tro ve dau dong
#define LCD_normal 0x06 //Che do nhap du lieu binh thuong
#define LCD_normal_s 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_off 0x08 //Tat man hinh
#define LCD_on 0x0C //Bat man hinh
#define LCD_on_crsr 0x0E //Bat man hinh va con tro
#define LCD_on_blink 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_4b2l 0x28 //Che do 2 dong, giao tiep 4 bit du lieu
#define LCD_homeL1 0x80 //Ve dau dong 1
#define LCD_homeL2 0xC0 //Ve dau dong 2
#define lcd_line_two 0x40
//#define ADCBUF 0x60

/*#define c1 0x66
#define c2 0x68
#define c3 0x6A
//#define c4 0x6C */

//int x;
//float y;
//char z;
//#define LED _LATE0 //LED noi vao RE0
//#define LED _LATE1 //LED noi vao RE0

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void); //Khoi tao cac cong I/O
void Delay_ms(unsigned int); //Tao tre n ms
void Init_LCD(void); //Khoi tao LCD
void LCD_cmd4(unsigned char); //Xuat lenh ra LCD qua giao tiep 4-bit
void LCD_dat4(unsigned char); //Xuat du lieu ra LCD qua giao tiep 4-bit
void lcd_putstr(char *buffer); //Xuat 1 ky tu hay 1 chuoi ky tu
void lcd_gotoxy(int x, int y ); //Nhay den cot x, hang y


//------------------------------------------------------------------------------
//Chuong trinh chinh
void main(void)
{
_TRISE3 = 0;
Init_PORTS(); //Khoi tao cac cong I/O

Init_ADC10(); //Khoi tao module ADC

Init_LCD(); //Khoi tao LCD
lcd_putstr(read());
lcd_gotoxy(4,2);
lcd_putstr("DC_DC CONVERTER");

}


//Chuong trinh con khoi tao cac cong I/O, de noi voi LED
//------------------------------------------------------------------------------
void Init_PORTS(void)
{
LATB= 0; //Xoa thanh ghi chot cong B
LCD_D4 = 0; //Xoa cac bit chot du lieu LCD
LCD_D5 = 0;
LCD_D6 = 0;
LCD_D7 = 0;

TRIS_LCD_D4 = 0; //Cac chan du lieu LCD la ngo ra
TRIS_LCD_D5 = 0;
TRIS_LCD_D6 = 0;
TRIS_LCD_D7 = 0;

LCD_EN = 0;
_TRISC13 = 0; //RE8 la ngo ra, noi vao Enable cua LCD
LCD_RW = 0;
_TRISB6 = 0; //RD0 la ngo ra, noi vao R/W cua LCD
LCD_RS = 0;
_TRISB7 = 0; //RD1 la ngo ra, noi vao Reset cua LCD
ADPCFG = 0xFFFF; //RB0..RB4 la cac chan digital
SW_TRIS = 0x001F; //Cac chan du lieu RB0..RB4 la ngo vao

}

//Chuong trinh con delay bang timer 1, tre n ms
//TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
//------------------------------------------------------------------------------
void Delay_ms(unsigned int n)
{
TMR1 = 0; //Xoa so dem trong TMR1
T1CON = 0x0020; //Dung fcy lam clock, prescale = 1:64, tat Timer 1
PR1 = n*ms_count; //Dat nguong tran vao PR1
T1CONbits.TON = 1; //Bat timer 1
while (!_T1IF ); //Cho den khi het thoi gian cho
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CONbits.TON = 0; //Tat timer 1

}

//Chuong trinh con khoi tao module LCD
//------------------------------------------------------------------------------
void Init_LCD(void) {
LCD_cmd4(LCD_4b2l); //Dat che do giao tiep 4-bit, man hinh 2 dong
Delay_ms(2);
LCD_cmd4(LCD_off); //Tat man hinh
Delay_ms(2);
LCD_cmd4(LCD_normal); //Che do nhap du lieu binh thuong
Delay_ms(2);
LCD_cmd4(LCD_on); //Bat man hinh, hien con tro nhap nhay
Delay_ms(2);
LCD_cmd4(LCD_clear); //Xoa man hinh
Delay_ms(5);

}

//Chuong trinh con xuat lenh o che do 4 bit
//------------------------------------------------------------------------------
void LCD_cmd4(unsigned char cmd) {
unsigned temp1, i;
LCD_RW = 0;
LCD_RS = 0; //Dat che do xuat lenh
temp1 = cmd >> 4; //Lay 4 bit cao
LCD_D4 = temp1 & 1; //Xuat 4 bit cao
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp1 = cmd & 0x0F; //Lay 4 bit thap
LCD_D4 = temp1 & 1; //Xuat 4 bit thap
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh con xuat du lieu o che do 4 bit
//------------------------------------------------------------------------------
void LCD_dat4(unsigned char dat) {
unsigned temp2, i;
LCD_RW = 0;
LCD_RS = 1; //Dat che do xuat du lieu
temp2 = dat >> 4; //Lay 4 bit cao
LCD_D4 = temp2 & 1; //Xuat 4 bit cao
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp2 = dat & 0x0F; //Lay 4 bit thap
LCD_D4 = temp2 & 1; //Xuat 4 bit thap
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 2; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}
//Chuong trinh con xuat 1 ky tu hay 1 chuoi ky tu
//------------------------------------------------------------------------------
void lcd_putstr(char *buffer)
{

while(*buffer != '\0')
{
LCD_dat4(*buffer); /* calling another function */
/* to write each char to the lcd module */
buffer++;
Delay_ms(2);

}
}
//Chuong trinh con nhay den cot x, dong y
//------------------------------------------------------------------------------
void lcd_gotoxy(int x, int y)
{
int address;

if(y != 1) address = lcd_line_two;
else address=0;

address += x-1;
LCD_cmd4( 0x80 | address);
Delay_ms(1);
}
void _ISR _T1Interrupt(void) {
_T1IF = 0; //Xoa co ngat
_LATE0 ^= 1; //Lat trang thai LED
_LATE1 ^= 1; //Lat trang thai LED
}


//Chuong trinh con khoi tao module chuyen doi A/D, doc ngo vao AN0
void Init_ADC10(void) {
ADPCFG = 0xFFEF; //Cac chan khac la digital, chan AN0/RB0 la analog
ADCON1 = 0x0060; //Module PWM cham dut lay mau va kich hoat
//viec chuyen doi A/D

ADCON2 = 0;
ADCHS = 0; //Kenh 0 doc tin hieu giua AN0 va AVss
ADCSSL = 0; //Khong quet cac ngo vao
ADCON3 = 0x0103; //Dung 1 TAD cho lay mau, dung clock he thong,
//TAD = 2xTcy = 250 ns
_ADIF = 0; //Xoa co ngat ADC
_ADIE = 1; //Cho phep ngat ADC
_ADON = 1; //Bat module ADC
_ASAM = 1; //Khoi dong che do tu dong lay mau
}
//Trinh phuc vu ngat cho ADC
/*void _ISR _ADCInterrupt(void)
{
ADCValue = ADCBUF0 >> 1; //Chi lay 9-bit cao nhat cua ket qua ADC
PDC1 = ADCValue; //Cap nhat cac thanh ghi dem chu ky nhiem vu
PDC2 = ADCValue;
PDC3 = ADCValue;
_ADIF = 0;
} */

read(void)
{
int a ;
float b;
a= ADCBUF0;
b=a*5/1024;
sprintf(b);

namqn
14-04-2009, 05:10 PM
Code của bạn post lên vẫn chưa hoàn chỉnh, vì hàm read() vẫn còn thiếu.

Bạn không nên gọi hàm read() trong hàm lcd_putstr(). Hàm lcd_putstr() của bạn cần một đối số là một chuỗi ký tự (thực tế chỉ có con trỏ đến chuỗi ký tự được truyền đến cho hàm lcd_putstr()), do đó bạn nên dùng một chuỗi ký tự để chứa các ký tự cần hiển thị lên LCD. Giả sử bạn khai báo một chuỗi ký tự toàn cục (global) đó là char *buf (tức là đặt khai báo này bên ngoài main() và tất cả các hàm khác), trong hàm read() bạn có thể gọi hàm sprintf() như sau để có được chuỗi ký tự biểu diễn cho giá trị float:
int a;
float b;
a = ADCBUF0;
b = ((float) a*5)/1024;
sprintf(buf, "%f", b);
Sau khi bạn gọi hàm read(), chuỗi buf sẽ chứa các ký tự biểu diễn cho giá trị float b, sẵn sàng để hiển thị trên LCD bằng hàm lcd_putstr().

Bạn nên đọc tài liệu mà tôi đã đề cập ở post trước đó, vì bạn chưa nắm rõ cú pháp của sprintf().

Thân,

popeye_ts22
28-10-2009, 04:21 PM
TUT của bác Nam về LCD trong C30 có áp dụng cho PIC24 được không ạ

popeye_ts22
28-10-2009, 05:11 PM
Đoạn code sau em dựa vào thư viện lcd_lib_8bit của CCS, chạy trên CCS cho PIC24FJ128GA010 rùi nhưng khi chỉnh sửa cho sang C30 thì không báo lỗi nhưng cũng không thấy hiện tượng gì, các bác giúp em với
#include <p24FJ128GA010.h>
#include <string.h>
_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRI)
///////////////////////
#define RS LATD15
#define RW LATD5
#define E LATD4
#define LCD PORTE
/*Ham yeu cau goi lenh dieu khien LCD*/
void comnwrt(void)
{
LATDbits.RS = 0;
LATDbits.RW = 0;
LATDbits.E = 1;
LATDbits.E = 0;
DelayMs(1);
}
/*Ham yeu cau goi du lieu hien thi len LCD*/
void datawrt(void)
{
LATDbits.RS = 1;
LATDbits.RW = 0;
LATDbits.E = 1;
LATDbits.E = 0;
DelayMs(1);
}
void lcd_init(void)
{
DelayMs(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();
}
void lcd_putcmd(unsigned int Cx)
{
LCD=Cx;
comnwrt();
}
void lcd_putchar(char Cx)
{
unsigned char x=0;unsigned char i=0;
x=(strlen(Cx));
for(i=0;i<=x;i++)
{
if(Cx==' ')i=i+2;
LCD=Cx;
datawrt();
}
}
///////////////////
int main(void)
{
_TRISD4=0;
LATDbits.E=0;
_TRISD5=0;
LATDbits.RW=0;
_TRISD15=0;
LATDbits.RS=0;
TRISE=0xFFF0;
lcd_init();
DelayMs(1000);
lcd_putcmd(0x01);
while(1);
{
lcd_putcmd(0x80);
lcd_putchar("PIC");
DelayMs(5000);
}
}

harakiri
07-11-2009, 06:30 PM
Mình viết đoạn code này để xuất một chuỗi kí tự và số lên trên máy tính, quá trình truyền là ok. Tuy nhiên, khi dùng hàm delay_us hay delay_ms qua trình truyền lại không xảy ra.
Đây là code :


#include<p33fj256gp710.h>
#include<stdio.h>
_FOSCSEL(FNOSC_FRC); // Internal FRC oscillator
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);
// Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystal

//unsigned int a,b,c,d;
#define ms_count 125 ;
unsigned int time_out,m,x,y;
unsigned char sbuf[200],c='C',t='T';

void __attribute__ ((interrupt, no_auto_psv)) _U1RXInterrupt(void) {
LATA = U1RXREG;
IFS0bits.U1RXIF = 0; //interrupt request has not occurred
}
void __attribute__ ((interrupt, no_auto_psv)) _U1TXInterrupt(void) {
IFS0bits.U1TXIF = 0;
}

void InitClock() {
PLLFBD = 38; // M = 40
CLKDIVbits.PLLPOST = 0; // N1 = 2
CLKDIVbits.PLLPRE = 0; // N2 = 2
OSCTUN = 0;//khong su dung oscillator tuning register
RCONbits.SWDTEN = 0; // disabe watch dog timer

// Clock switch to incorporate PLL
__builtin_write_OSCCONH(0x01); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
// luu y : doc thanh ghi OSCCON de thay
__builtin_write_OSCCONL(0x01); // Start clock switching
//ghi lan luot vao 8 bit cao va thap cua OSCCON
while (OSCCONbits.COSC != 0b001); // Wait for Clock switch to occur

while(OSCCONbits.LOCK != 1) {}; //pll lock status bit
}

void InitUART1() {

// configure U2MODE
U1MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
//U2MODEbits.notimplemented; // Bit14
U1MODEbits.USIDL = 0; // Bit13 Continue in Idle
U1MODEbits.IREN = 0; // Bit12 No IR translation
U1MODEbits.RTSMD = 0; // Bit11 Simplex Mode
//U1MODEbits.notimplemented; // Bit10
U1MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
U1MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here)
U1MODEbits.LPBACK = 0; // Bit6 No Loop Back
U1MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
U1MODEbits.URXINV = 0; // Bit4 IdleState = 1 (for dsPIC)
U1MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
U1MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
U1MODEbits.STSEL = 0; // Bit0 One Stop Bit

// Baud Rate Generator is for 9600.
// See section 19.3.1 of datasheet.
// U1BRG = (Fcy/(16*BaudRate))-1
// U1BRG = (37M/(16*9600))-1
// U1BRG = 240
U1BRG = 239; // 40Mhz osc, 9600 Baud, baud rate = Fcy/[16x(UxBRG+1)]

// Load all values in for U1STA SFR
U1STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
U1STAbits.UTXINV = 0; //Bit14 N/A, IRDA config
U1STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
//U2STAbits.notimplemented = 0; //Bit12
U1STAbits.UTXBRK = 0; //Bit11 Disabled
U1STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
U1STAbits.UTXBF = 0; //Bit9 *Read Only Bit*
U1STAbits.TRMT = 0; //Bit8 *Read Only bit*
U1STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
U1STAbits.ADDEN = 0; //Bit5 Address Detect Disabled
U1STAbits.RIDLE = 0; //Bit4 *Read Only Bit*
U1STAbits.PERR = 0; //Bit3 *Read Only Bit*
U1STAbits.FERR = 0; //Bit2 *Read Only Bit*
U1STAbits.OERR = 0; //Bit1 *Read Only Bit*
U1STAbits.URXDA = 0; //Bit0 *Read Only Bit*

IPC7 = 0x4400; // Mid Range Interrupt Priority level, no urgent reason

IFS0bits.U1TXIF = 0; // Clear the Transmit Interrupt Flag
IEC0bits.U1TXIE = 1; // Enable Transmit Interrupts
IFS0bits.U1RXIF = 0; // Clear the Recieve Interrupt Flag
IEC0bits.U1RXIE = 1; // Enable Recieve Interrupts

U1MODEbits.UARTEN = 1; // And turn the peripheral on

U1STAbits.UTXEN = 1;

}


int main(void) {

InitClock(); // This is the PLL settings

InitUART1(); // Initialize UART2 for 9600,8,N,1 TX/RX

while(1){ // The ever versatile Infinite Loop!

sprintf(sbuf,"%c%c %i %i %i %i %i %i \n",'T','C',20,40,40,60,30,10);
putsUART1(sbuf);

}
}
/************************************************** *************************
* Function Name : putsUART1 *
* Description : This function puts the data string to be transmitted *
* into the transmit buffer (till NULL character) *
* Parameters : unsigned int * address of the string buffer to be *
* transmitted *
* Return Value : None *
************************************************** *************************/

void putsUART1(unsigned int *buffer)
{
char * temp_ptr = (char *) buffer;

/* transmit till NULL character is encountered */

if(U1MODEbits.PDSEL == 3) /* check if TX is 8bits or 9bits */
{
while(*buffer != '\0')
{
while(U1STAbits.UTXBF); /* wait if the buffer is full */

U1TXREG = *buffer++; /* transfer data word to TX reg */
delay_us(100);
}
}
else
{
while(*temp_ptr != '\0')
{
while(U1STAbits.UTXBF); /* wait if the buffer is full */

U1TXREG = *temp_ptr++; /* transfer data byte to TX reg */
delay_us(100);
}
}
}
/************************************************** *****************************************
//Function: void Init_TMR1(void)
//Input: None
//Output: Setup Parameter to Timer1 Operate
// TMR1 use for delay
************************************************** *****************************************/
void Init_TMR1(void)
{
T1CONbits.TON=0; //Stop Timer1
T1CONbits.TGATE=0; //Disable Gated Timer mode
T1CONbits.TCKPS=2; //Select Prescale 1:1
T1CONbits.TCS=0; //Internal clock
PR1=ms_count;
_T1IF=0;
_T1IE=1;
TMR1=0;
}
/************************************************** *****************************************
//Function: void delay_us(unsigned int n)
//Input: n: n us to delay
//Output: Delay n us
************************************************** *****************************************/
void delay_us(unsigned int n)
{
PR1=n*ms_count;
time_out=0;
T1CONbits.TON=1;
while(time_out==0);
T1CONbits.TON = 0;
TMR1=0;
}
/************************************************** *****************************************
//Function: void delay_ms(unsigned int n)
//Input: n: n ms to delay
//Output: Delay n ms
************************************************** *****************************************/
void delay_ms(unsigned int n)
{
unsigned int i;
i=0;
while(i<=n)
{
delay_us(1000);
i++;
}
}
void _ISR _T1Interrupt(void)
{
_T1IF = 0; //Clear Timer1 flag
time_out = 1;
}

namqn
07-11-2009, 10:02 PM
Mình viết đoạn code này để xuất một chuỗi kí tự và số lên trên máy tính, quá trình truyền là ok. Tuy nhiên, khi dùng hàm delay_us hay delay_ms qua trình truyền lại không xảy ra.
Đây là code :
...
Có vẻ bạn áp dụng một cách máy móc kỹ thuật delay dùng Timer 1 trong tutorial mà không hiểu về nó. Có chắc đoạn code delay_us(n) sẽ làm trễ n micro giây không?

Bạn có hàm Init_TMR1() trong source code, nhưng không hề gọi nó trong main(), vậy Timer 1 sẽ được thiết lập ra sao?

Thân,

harakiri
08-11-2009, 01:34 AM
Cám ơn anh Nam. Hàm delay là do em thử một trị khác trị tính toán ban đầu nên nó lung tung,không chính xác. Loay hoay tìm nhưng rốt cuộc lại bị lỗi là chưa gọi hàm Init_TMR1(). Một bài học đắt giá cho kinh nghiệm rất ít của em. Sau khi gửi lên máy tính xong, trong hàm main em viết thêm một câu lệnh nhận rất đơn giản (với biến temp em khai bao thuoc kieu char) rồi sau đó gửi ngược lên. Tuy nhiên nó lại không chạy. Nhân đây cho em hỏi, nếu mình muốn nhận về một chuỗi ký tự thì mình tách chuỗi thế nào để nhận được .
************************************************** *******
int main(void) {

InitClock(); // This is the PLL settings
Init_TMR1();
InitUART1(); // Initialize UART2 for 9600,8,N,1 TX/RX


while(1) { // The ever versatile Infinite Loop!
if (U1STAbits.URXDA==1)
{
temp=U1RXREG;
delay_ms(10);
U1TXREG=temp;
}
}
}
************************************************** ******
Còn khi em thử dùng hàm sau để kiểm tra thử :
*******************************
if (U1STAbits.URXDA==1){
U1TXREG='A';
}
else
{delay_ms(50);
U1TXREG='B';
}
********************************
thì kết quả là trên máy tính luôn nhận 'A'.

namqn
08-11-2009, 10:10 PM
Cám ơn anh Nam. Hàm delay là do em thử một trị khác trị tính toán ban đầu nên nó lung tung,không chính xác. Loay hoay tìm nhưng rốt cuộc lại bị lỗi là chưa gọi hàm Init_TMR1(). Một bài học đắt giá cho kinh nghiệm rất ít của em. Sau khi gửi lên máy tính xong, trong hàm main em viết thêm một câu lệnh nhận rất đơn giản (với biến temp em khai bao thuoc kieu char) rồi sau đó gửi ngược lên. Tuy nhiên nó lại không chạy. Nhân đây cho em hỏi, nếu mình muốn nhận về một chuỗi ký tự thì mình tách chuỗi thế nào để nhận được .
************************************************** *******
int main(void) {

InitClock(); // This is the PLL settings
Init_TMR1();
InitUART1(); // Initialize UART2 for 9600,8,N,1 TX/RX


while(1) { // The ever versatile Infinite Loop!
if (U1STAbits.URXDA==1)
{
temp=U1RXREG;
delay_ms(10);
U1TXREG=temp;
}
}
}
************************************************** ******
Còn khi em thử dùng hàm sau để kiểm tra thử :
*******************************
if (U1STAbits.URXDA==1){
U1TXREG='A';
}
else
{delay_ms(50);
U1TXREG='B';
}
********************************
thì kết quả là trên máy tính luôn nhận 'A'.
Nếu U1STAbits.URXDA bằng '1' thì có dữ liệu để đọc, nên đọc cho đến khi hết dữ liệu trong bộ đệm rồi hẵng dừng. Trong quá trình đọc có thể xuất dữ liệu ngược lại nguồn phát.

Đoạn code đầu tiên của bạn có gọi hàm delay_ms(), không rõ hàm này sẽ delay bao lâu, do đó không nên dùng nó. Đoạn code thứ hai thì rơi vào tình trạng nếu U1STAbits.URXDA bằng '1' thì nó sẽ luôn luôn rơi vào nhánh if, vì trong nhánh if đó bạn không bao giờ đọc dữ liệu ra khỏi bộ đệm để cờ URXDA được xóa về '0'.

Trong đoạn code thử của bạn, bạn nên bỏ hẳn lệnh gọi hàm delay_ms() đi, và phát ngay sau khi nhận được dữ liệu xem. Như vậy dsPIC sẽ chờ đến khi có dữ liệu và phát trả lại dữ liệu ngay khi đọc từ bộ đệm. Đây là cách tôi vẫn thử các module UART.

Thân,

ngoducbinh1987
03-12-2009, 12:03 AM
em đang tập hiện LCD với dspic 30f4013. em có tham khảo mấy bài trong này và chỉnh sửa lại. Nhưng mà không thấy nó chạy gì cả. Anh em nào hảo tâm giúp mình với

kienvtc
05-05-2010, 01:59 AM
Cho mình hỏi chút. Đã ai gặp trường hợp các chân RE8,RF2,RF3 không cấu hình được cho mục đích IO, các chân khác vẫn bình thường và thử qua một số mạch in khác nhau vẫn gặp trường hợp tương tự. Sử dụng module của dsPic như UART hay I2C vẫn chạy bình thường. Mình thử mọi cách mà ko được. Chắc cấu hình sai ở đâu đấy. Có bạn nào gặp trường hợp tương tự thì trả lời giúp.

hopeman
05-05-2010, 12:59 PM
bạn phải cho biết loại chip mình dùng, có thể là cả mạch và code của bạn nữa thì mọi người mới giúp được.

minhthaitn
05-10-2010, 08:09 PM
Em dùng explorer 16 và code lại theo TUT của anh Nam nhưng không thấy LCD hiện gì, em debug với ICD2 mà không chạy
RD4 EN
RD5 RW
RD15 RS
các chân data RE(RE0-RE7)
em dùng C30
anh xem hộ em sai chỗ nào với ạ, em cảm ơn
code:
#include <p33FJ256GP710.h>

_FOSCSEL(FNOSC_FRC)
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);

_FWDT(FWDTEN_OFF);
// _FBORPOR(PBOR_OFF & MCLR_EN & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(GSS_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)

#define ms_count 125 //So dem tuong ung voi 1 ms, cho timer 1


#define LCD_EN _LATD4 //Tin hieu Enable cho LCD, chan RD4
#define LCD_RW _LATD5 //Tin hieu Read/Write cho LCD, chan RD5
#define LCD_RS _LATD15 //Tin hieu Reset cho LCD, chan RD15
#define LCD_DAT LATE //Cac tin hieu Data cho LCD, chan RE0..RE7
#define LCD_TRIS TRISE //Tristate cua cac tin hieu Data cho LCD

#define LCD_clear 0x01 //Xoa man hinh LCD
#define LCD_home 0x02 //Tro ve dau dong
#define LCD_normal 0x06 //Che do nhap du lieu binh thuong
#define LCD_normal_s 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_off 0x08 //Tat man hinh
#define LCD_on 0x0C //Bat man hinh
#define LCD_on_crsr 0x0E //Bat man hinh va con tro
#define LCD_on_blink 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_4b2l 0x28 //Che do 2 dong, giao tiep 4 bit du lieu
#define LCD_homeL1 0x80 //Ve dau dong 1
#define LCD_homeL2 0xC0 //Ve dau dong 2

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void); //Khoi tao cac cong I/O
void Init_TMR1(void); //Khoi tao Timer 1
void Delay_ms(unsigned int); //Tao tre mot so ms
void Init_LCD(void); //Khoi tao LCD
void LCD_cmd4(unsigned char); //Xuat lenh ra LCD qua giao tiep 4-bit
void LCD_dat4(unsigned char); //Xuat du lieu ra LCD qua giao tiep 4-bit

//Bang hang so trong ROM
const unsigned char __attribute__ ((space(psv), address (0x0400)))
//Chuoi ky tu se xuat ra LCD
Chuoi1[]="Hello world!\0"; //Chuoi ky tu se duoc xuat ra LCD

//Cac bien toan cuc
unsigned char time_out, idx;

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
_PLLPRE = 0;
_PLLPOST = 1;
_PLLDIV = 30;
while( _COSC != 0b001 ){
Init_TMR1(); //Khoi tao cho TMR1
Init_PORTS(); //Khoi tao cac cong I/O
_PSV=1;
PSVPAG = __builtin_psvpage(Chuoi1);
idx = 0;
Delay_ms(50);
Init_LCD();
Delay_ms(500);
while (Chuoi1[idx]) { //Xuat chuoi ra dong thu nhat cua LCD
LCD_dat4(Chuoi1[idx++]);
Delay_ms(1);
};
LCD_cmd4(LCD_homeL2);
Delay_ms(1);
idx = 0;
while (Chuoi1[idx]) { //Xuat chuoi ra dong thu hai cua LCD
LCD_dat4(Chuoi1[idx]);
Delay_ms(1);
idx ++;
};
while (1) {}; //Vong lap chinh

}
}

//Chuong trinh con khoi tao Timer 1
//TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
//------------------------------------------------------------------------------
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = ms_count; //TMR1 tran moi ms
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x0030; //Dung fcy lam clock, prescale = 1:64, tat Timer 1
_T1IE = 1; //Cho phep ngat Timer 1
}

//Chuong trinh con khoi tao cac cong I/O, de noi voi LED
//------------------------------------------------------------------------------
void Init_PORTS(void) {
LCD_DAT = 0xFF00; //Xoa cac bit chot du lieu LCD
LCD_TRIS = 0xFF00; //Cac chan du lieu LCD la ngo ra
LCD_EN = 0;
_TRISD4 = 0; //RD4 la ngo ra, noi vao Enable cua LCD
LCD_RW = 0;
_TRISD5 = 0; //RD5 la ngo ra, noi vao R/W cua LCD
LCD_RS = 0;
_TRISD15 = 0; //RD15 la ngo ra, noi vao Reset cua LCD
}

//Chuong trinh con delay bang timer 1, nhan 1 tham so la so ms can delay
//------------------------------------------------------------------------------
void Delay_ms(unsigned n) {
PR1 = n * ms_count; //Dat nguong tran vao PR1

T1CONbits.TON = 1; //Bat timer 1

}

//Chuong trinh con khoi tao module LCD
//------------------------------------------------------------------------------
void Init_LCD(void) {
LCD_cmd4(LCD_4b2l); //Dat che do giao tiep 4-bit, man hinh 2 dong
Delay_ms(1);
LCD_cmd4(LCD_off); //Tat man hinh
Delay_ms(1);
LCD_cmd4(LCD_normal); //Che do nhap du lieu binh thuong
Delay_ms(1);
LCD_cmd4(LCD_on_blink); //Bat man hinh, hien con tro nhap nhay
Delay_ms(1);
LCD_cmd4(LCD_clear); //Xoa man hinh
Delay_ms(5);

}

//Chuong trinh con xuat lenh o che do 4 bit
//------------------------------------------------------------------------------
void LCD_cmd4(unsigned char cmd) {
unsigned temp1, i;
LCD_RW = 0;
LCD_RS = 0; //Dat che do xuat lenh
temp1 = LCD_DAT & 0xFF00; //Lay trang thai hien thoi cua LCD_DAT
LCD_DAT = temp1 | (cmd ); //Xuat 4 bit cao
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 8; i++); //keo dai toi thieu 1 us
LCD_EN = 0;

}

//Chuong trinh con xuat du lieu o che do 4 bit
//------------------------------------------------------------------------------
void LCD_dat4(unsigned char dat) {
unsigned temp2, i;
LCD_RW = 0;
LCD_RS = 1; //Dat che do xuat du lieu
temp2 = LCD_DAT & 0xFF00; //Lay trang thai hien thoi cua LCD_DAT
LCD_DAT = temp2 | (dat ); //Xuat 4 bit cao
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 8; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh xu ly ngat Timer 1
//------------------------------------------------------------------------------
void _ISR _T1Interrupt(void) {
T1CONbits.TON = 0; //Tat timer 1
_T1IF = 0; //Xoa co ngat
TMR1 = 0;
}

lenh_tap_ket
15-05-2011, 02:10 PM
Sao em làm mà không được, bác xem hộ em xem code có sai chỗ nào không ạ. Mà nó toàn hiển thị mỗi chữ O không à
#include "p30f4011.h"

_FOSC(CSW_FSCM_OFF & FRC_PLL4); //Clock = 32 MHz
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)

#define ms_count 125 //So dem tuong ung voi 1 ms, cho timer 1


#define LCD_RS _LATF0 //Tin hieu Reset cho LCD, chan RD1
#define LCD_RW _LATF1 //Tin hieu Read/Write cho LCD, chan RD0
#define LCD_EN _LATF2 //Tin hieu Enable cho LCD, chan RE8

#define LCD_D4 _LATF3 //Cac tin hieu Data cho LCD, chan (D4..D7)
#define LCD_D5 _LATF4
#define LCD_D6 _LATF5
#define LCD_D7 _LATF6

#define TRIS_LCD_D4 _TRISF3 //Tristate cua cac tin hieu Data cho LCD
#define TRIS_LCD_D5 _TRISF4
#define TRIS_LCD_D6 _TRISF5
#define TRIS_LCD_D7 _TRISF6

#define LCD_clear 0x01 //Xoa man hinh LCD
#define LCD_home 0x02 //Tro ve dau dong
#define LCD_normal 0x06 //Che do nhap du lieu binh thuong
#define LCD_normal_s 0x07 //Che do nhap du lieu binh thuong, dich man hinh
#define LCD_off 0x08 //Tat man hinh
#define LCD_on 0x0C //Bat man hinh
#define LCD_on_crsr 0x0E //Bat man hinh va con tro
#define LCD_on_blink 0x0F //Bat man hinh va con tro (nhap nhay)
#define LCD_4b2l 0x28 //Che do 2 dong, giao tiep 4 bit du lieu
#define LCD_homeL1 0x80 //Ve dau dong 1
#define LCD_homeL2 0xC0 //Ve dau dong 2

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void); //Khoi tao cac cong I/O
void Init_TMR1(void); //Khoi tao Timer 1
void Delay_ms(unsigned int); //Tao tre mot so ms
void Init_LCD(void); //Khoi tao LCD
void LCD_cmd4(unsigned char); //Xuat lenh ra LCD qua giao tiep 4-bit
void LCD_dat4(unsigned char); //Xuat du lieu ra LCD qua giao tiep 4-bit

//Bang hang so trong ROM
char chuoi1[]="Hello world!"; //Chuoi ky tu se duoc xuat ra LCD

//Cac bien toan cuc
unsigned char time_out,idx;

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
_TRISE0 = 0;
Init_TMR1(); //Khoi tao cho TMR1
Init_PORTS(); //Khoi tao cac cong I/O
idx = 0;
Init_LCD();
Delay_ms(500);
LCD_cmd4(LCD_homeL1);
LCD_dat4('H');

while (1) {
_LATE0=1;
Delay_ms(250); //Vong lap chinh
_LATE0=0;
Delay_ms(250);
};
}

//Chuong trinh con khoi tao Timer 1
//TMR1 duoc dung de dem so ms troi qua, o muc xung 8 Mips (fcy = 8 MHz)
//------------------------------------------------------------------------------
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = ms_count; //TMR1 tran moi ms
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x0020; //Dung fcy lam clock, prescale = 1:64, tat Timer 1
_T1IE = 1; //Cho phep ngat Timer 1
}

//Chuong trinh con khoi tao cac cong I/O, de noi voi LED
//------------------------------------------------------------------------------
void Init_PORTS(void)
{
LCD_D4 = 0; //Xoa cac bit chot du lieu LCD
LCD_D5 = 0;
LCD_D6 = 0;
LCD_D7 = 0;

TRIS_LCD_D4 = 0; //Cac chan du lieu LCD la ngo ra
TRIS_LCD_D5 = 0;
TRIS_LCD_D6 = 0;
TRIS_LCD_D7 = 0;

LCD_EN = 0;
_TRISF2 = 0; //RE8 la ngo ra, noi vao Enable cua LCD
LCD_RW = 0;
_TRISF1 = 0; //RD0 la ngo ra, noi vao R/W cua LCD
LCD_RS = 0;
_TRISF0 = 0; //RD1 la ngo ra, noi vao Reset cua LCD
}

//Chuong trinh con delay bang timer 1, nhan 1 tham so la so ms can delay
//------------------------------------------------------------------------------
void Delay_ms(unsigned n) {
PR1 = n*ms_count; //Dat nguong tran vao PR1
time_out = 0; //Xoa co het thoi gian cho
T1CONbits.TON = 1; //Bat timer 1
while (time_out == 0); //Cho den khi het thoi gian cho
T1CONbits.TON = 0; //Tat timer 1
TMR1 = 0;
}

//Chuong trinh con khoi tao module LCD
//------------------------------------------------------------------------------
void Init_LCD(void) {
LCD_cmd4(LCD_4b2l); //Dat che do giao tiep 4-bit, man hinh 2 dong
Delay_ms(1);
LCD_cmd4(LCD_off); //Tat man hinh
Delay_ms(1);
LCD_cmd4(LCD_normal); //Che do nhap du lieu binh thuong
Delay_ms(1);
LCD_cmd4(LCD_on); //Bat man hinh, hien con tro nhap nhay
Delay_ms(1);
LCD_cmd4(LCD_clear); //Xoa man hinh
Delay_ms(5);

}

//Chuong trinh con xuat lenh o che do 4 bit
//------------------------------------------------------------------------------
void LCD_cmd4(unsigned char cmd) {
unsigned temp1, i;
LCD_RW = 0;
LCD_RS = 0; //Dat che do xuat lenh
temp1 = cmd >> 4; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp1 & 1; //Xuat 4 bit cao
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 10; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp1 = cmd & 0x0F; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp1 & 1; //Xuat 4 bit thap
LCD_D5 = (temp1 & 2) >>1;
LCD_D6 = (temp1 & 4) >>2;
LCD_D7 = (temp1 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 10; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh con xuat du lieu o che do 4 bit
//------------------------------------------------------------------------------
void LCD_dat4(unsigned char dat) {
unsigned temp2, i;
LCD_RW = 0;
LCD_RS = 1; //Dat che do xuat du lieu
temp2 = dat >> 4; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp2 & 1; //Xuat 4 bit cao
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 10; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
temp2 = dat & 0x0F; //Lay trang thai hien thoi cua LCD_DAT
LCD_D4 = temp2 & 1; //Xuat 4 bit thap
LCD_D5 = (temp2 & 2) >>1;
LCD_D6 = (temp2 & 4) >>2;
LCD_D7 = (temp2 & 8) >>3;
LCD_EN = 1; //Tao xung Enable
for (i = 0; i < 10; i++); //keo dai toi thieu 1 us
LCD_EN = 0;
}

//Chuong trinh xu ly ngat Timer 1
//------------------------------------------------------------------------------
void _ISR _T1Interrupt(void) {
_T1IF = 0; //Xoa co ngat
time_out = 1;
}

nammta
29-07-2011, 10:41 AM
mình thấy thread này có 87 mấy trang sao vào chỉ có 6

raitahn
23-09-2012, 12:04 AM
các bạn ơi cho mình hỏi:hiển thị Tiếng Việt cho ma trận LED 32X16

provaidan
04-10-2012, 09:58 PM
anh ơi link hong rồi kia,a cho e hỏi,e đang làm việc với dspic33fj32mc202,e ko thấy chân sử dụng Input Capture là pin nào?a giúp e với
thank nhiều!

ntquang_1992
28-10-2012, 09:34 AM
Cho em hỏi đoạn code dsPic4011 xuất ra lcd không biết bị gì mà lcd hiển thị sai, khi e xuất chữ "QUANG" thì nó bị giật giật và không đủ chữ nó chỉ có "QANG" nhiều lúc nó còn dịch trái nữa, có khi nào bị lỗi phần cứng không ạ, e viết bằng mikroC
sbit LCD_RS at LATB0_bit;
sbit LCD_EN at LATB2_bit;
sbit LCD_D4 at LATB4_bit;
sbit LCD_D5 at LATB5_bit;
sbit LCD_D6 at LATB6_bit;
sbit LCD_D7 at LATB7_bit;

sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB2_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
char txt1[] = "Quang";
void main() {
ADPCFG = 0xFFFF; // Configure AN pins as digital I/O
TRISB.F1=0;
LATB1_bit=0;
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
while(1)
{
Lcd_Out(2,3,txt1); // Write text in second row
Delay_ms(2000);
}

}

sinhngoc2008
25-03-2013, 12:01 AM
Thầy Nam cho e xin cái thư viện dspic30f trên proteus để mô phỏng được ko ạh

sinhngoc2008
27-03-2013, 09:58 AM
Có ai có thư viện của dspic30f trên proteus ko cho mình xin với
Thanks!

thienquang07
08-11-2014, 03:51 PM
ai up lại cho mình xin với, link die hết rồi

okanhchaphet
19-02-2017, 11:15 PM
Đây là tutorial tiếp theo cho dsPIC, viết trong ASM30. Vài ngày tới tôi sẽ post các source code viết bằng C30 cho các tutorial đã viết. Các bạn theo dõi trong các luồng tương ứng của các tutorial đã post.

Trong tutorial 3 cho dsPIC, thông qua một ví dụ về đọc trạng thái các công tắc nối vào dsPIC và hiển thị trạng thái trên LCD, tôi minh hoạ cách đọc ngõ vào số của dsPIC, và cách giao tiếp dsPIC với LCD. Tôi cũng đã giới thiệu cách viết macro và cách định thời bằng ngắt với thời gian xử lý ngắt tối thiểu.

Link để download tutorial:
http://picvietnam.com/download/upload/namqn/TUT04.01.PVN.NQNT.180706.pdf

Các tập tin nguồn và hex được đặt trong tập tin nén sau:
http://picvietnam.com/download/upload/namqn/Vidu3.zip

Chúc các bạn thành công!

Thân,

thưa thầy, thầy có thể cho em xin full bộ tutorial về dspic đc không ạ