PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   dsPIC - Bộ điều khiển tín hiệu số 16-bit (http://www.picvietnam.com/forum/forumdisplay.php?f=29)
-   -   dsPIC Tutorial 4-Module UART và I2C (http://www.picvietnam.com/forum/showthread.php?t=623)

silvadk2 21-05-2009 01:12 PM

dây đó em chạy với 1 mạch khác, nó ok bác ạ! mà có mỗi 1 dây, ngại đi mua quá. với lại mạch kia chạy ok thì chắc dây ko vấn đề

silvadk2 21-05-2009 02:00 PM

Ô hô, em tìm ra lỗi rồi, do con vdk chết module uart, em thay con khác thì nó gửi ký tự rồi. Nhưng lạ 1 nỗi, cứ cắm com vào mt thì chip nóng ran. thế là thế nào nhỉ các bác. Néu cắm com mà ko cắm vào mt thì chip ko nóng, hic :(

namqn 21-05-2009 10:45 PM

Trích:

Nguyên văn bởi Hiepnv101 (Post 25738)
Anh Nam cho em hỏi. Em khai báo _FBORPOR(PBOR_OFF & MCLR_EN); thì truyền lên PC rất nhiễu. Nhưng khi khai báo _FBORPOR(PBOR_OFF & MCLR_DIS); thì lại truyền rất chuẩn. Anh có thể nêu qua 2 khai báo này được không ạ?

Thanks,

PBOR là viết tắt của Programmable Brown-Out Reset, tức là chức năng tự động reset khi nguồn suy giảm.

MCLR là viết tắt của Master Clear (Reset), tức là chức năng reset bộ xử lý khi chân MCLR được đặt ở trạng thái tích cực (mức logic '0').

Việc nhiễu khác nhau ở hai cấu hình của bạn thì vẫn chưa có đủ thông tin để góp ý. Bạn dùng sơ đồ nguyên lý như thế nào (chân MCLR của bạn được thiết kế ra sao, vì trong hai cấu hình thì chỉ có chức năng của chân MCLR là khác nhau)?

Thân,

conglong 07-09-2009 01:42 PM

Uart .
 
Thầy Nam và các anh chị trong diễn đàn cho em hỏi về một số liên quan tới UART của dsPIC.
Em đang làm đồ án môn học liên quan tới PID trên máy tính rồi truyền giá trị xuống cho dsPIC. Giá trị em muốn truyền là thông số cho PDC1 và PDC2 (hai thanh ghi thiết lập duty_cycle trong module PWM )cho 2 bánh của robot. hai giá trị em gửi xuống cho dsPIC có tầm từ 0 tới 1599. nên cho em hỏi là có cách nào truyền từ máy tính xuống mà 1 lúc truyền được 16 bit data không ?. em đang làm việc với VC++. em chỉ thấy 1 frame truyền được 8 bit data mà chưa thấy truyền 1 frame 16 bits data . Nếu không truyền được 16 bits data /frame thì bài toán vừa nêu em định làm như sau :
Với giá trị cho thanh ghi PDC1 : em truyền byte đầu (8 bits thấp) cho dsPIC , lưu giá trị này vào biến có tên là temp1 , sau đó truyền tiếp byte thứ 2 (8 bits cao) và lưu vào temp2 , sau đó thực hiện phép tính :
PDC1 = (temp2<<8) + temp1;
tương tự với giá trị truyền cho PDC2.
Nhưng em vẫn chưa biết cách thiết lập ngắt cho module UART khi nó nhận xong 4 byte (em muốn nhận xong 4 byte rồi ngắt). và lấy 4 byte vừa nhận ở những thanh ghi nào vì em chỉ thấy có 1 thanh ghi lưu giá trị mà dsPIC nhận thôi ah ?
Cảm ơn thầy và các anh chị nhiều .
Trân trọng !.

namqn 07-09-2009 04:05 PM

Trích:

Nguyên văn bởi conglong (Post 29370)
Thầy Nam và các anh chị trong diễn đàn cho em hỏi về một số liên quan tới UART của dsPIC.
Em đang làm đồ án môn học liên quan tới PID trên máy tính rồi truyền giá trị xuống cho dsPIC. Giá trị em muốn truyền là thông số cho PDC1 và PDC2 (hai thanh ghi thiết lập duty_cycle trong module PWM )cho 2 bánh của robot. hai giá trị em gửi xuống cho dsPIC có tầm từ 0 tới 1599. nên cho em hỏi là có cách nào truyền từ máy tính xuống mà 1 lúc truyền được 16 bit data không ?. em đang làm việc với VC++. em chỉ thấy 1 frame truyền được 8 bit data mà chưa thấy truyền 1 frame 16 bits data . Nếu không truyền được 16 bits data /frame thì bài toán vừa nêu em định làm như sau :
Với giá trị cho thanh ghi PDC1 : em truyền byte đầu (8 bits thấp) cho dsPIC , lưu giá trị này vào biến có tên là temp1 , sau đó truyền tiếp byte thứ 2 (8 bits cao) và lưu vào temp2 , sau đó thực hiện phép tính :
PDC1 = (temp2<<8) + temp1;
tương tự với giá trị truyền cho PDC2.
Nhưng em vẫn chưa biết cách thiết lập ngắt cho module UART khi nó nhận xong 4 byte (em muốn nhận xong 4 byte rồi ngắt). và lấy 4 byte vừa nhận ở những thanh ghi nào vì em chỉ thấy có 1 thanh ghi lưu giá trị mà dsPIC nhận thôi ah ?
Cảm ơn thầy và các anh chị nhiều .
Trân trọng !.

Bạn sẽ không thể truyền 16 bit dữ liệu liên tiếp. Bạn tách 16 bit dữ liệu thành 2 byte là ổn. Để thiết lập module UART tạo ngắt sau khi nhận được 4 byte, bạn đặt các bit URXISEL<1:0> trong thanh ghi U1STA bằng '11' (giả sử bạn đang dùng module UART1).

Để lấy các byte dữ liệu khi có ngắt, bạn liên tiếp đọc thanh ghi U1RXREG (giả sử bạn đang dùng module UART1). Vì các module UARTx sử dụng bộ đệm FIFO (First-In First-Out), nên các byte được nhận trước sẽ được đọc ra trước. Cụ thể, ví dụ từ máy tính bạn lần lượt gửi các giá trị a, b, c, và d đến dsPIC. Sau khi nhận được giá trị d, dsPIC sẽ tạo ra ngắt, và khi xử lý ngắt, nếu bạn liên tiếp đọc thanh ghi U1RXREG thì bạn sẽ lần lượt nhận được các giá trị a, b, c, và d.

Thân,

conglong 07-09-2009 09:44 PM

Trích:

Nguyên văn bởi namqn (Post 29379)
Bạn sẽ không thể truyền 16 bit dữ liệu liên tiếp. Bạn tách 16 bit dữ liệu thành 2 byte là ổn. Để thiết lập module UART tạo ngắt sau khi nhận được 4 byte, bạn đặt các bit URXISEL<1:0> trong thanh ghi U1STA bằng '11' (giả sử bạn đang dùng module UART1).

Để lấy các byte dữ liệu khi có ngắt, bạn liên tiếp đọc thanh ghi U1RXREG (giả sử bạn đang dùng module UART1). Vì các module UARTx sử dụng bộ đệm FIFO (First-In First-Out), nên các byte được nhận trước sẽ được đọc ra trước. Cụ thể, ví dụ từ máy tính bạn lần lượt gửi các giá trị a, b, c, và d đến dsPIC. Sau khi nhận được giá trị d, dsPIC sẽ tạo ra ngắt, và khi xử lý ngắt, nếu bạn liên tiếp đọc thanh ghi U1RXREG thì bạn sẽ lần lượt nhận được các giá trị a, b, c, và d.

Thân,

ah, dạ em cảm ơn thầy nhiều !
Trân trọng !.

npbaoduy 30-10-2009 09:50 PM

Hỏi về giao tiếp I2C với ROM 24c512
 
Em có đoạn code như sau, với ý tưởng là lưu một byte vô ROM (0x66) vào địa chỉ 0001, sau đó đọc lại byte đó và gởi ra cổng nối tiếp, nhưng em không đạt kết quả (không gởi ra cổng nối tiếp được gì)
Code:

int main(void) {
        Init_PORTS();                //Khoi tao cac cong I/O
        Init_I2C();                        //Khoi tao module I2C
        Init_UART1_Module();
        Init_TMR1();
        //Buoc 1, tao dieu kien START, cho hoat dong I2C hoan tat
        _SEN = 1;
        Wait_I2C();                        //Cho hoat dong I2C hoan tat
        //Buoc 2, xuat dia chi cua ROM voi thao tac ghi, cho va kiem tra ACK
        Write_I2C(0xA0);                //Xuat dia chi cua ROM, sap ghi vao ROM
        Wait_I2C();                        //Cho hoat dong I2C hoan tat
        if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi dung chuong trinh
        //Buoc 3, xuat dia chi cua thanh ghi dich (target), cho va kiem tra ACK
        Write_I2C(0x00);                //Xuat dia chi cao
        Wait_I2C();                        //Cho hoat dong I2C hoan tat
        if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi dung chuong trinh
        Write_I2C(0x01);                //xuat dia chi thap
        Wait_I2C();                        //Cho hoat dong I2C hoan tat
        if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi dung chuong trinh
        Write_I2C(0x66);                //Xuat noi dung cua thanh ghi 0x0000
        Wait_I2C();                        //Cho hoat dong I2C hoan tat
        if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi dung chuong trinh
        _PEN = 1;        //Tao ra dieu kien STOP
        Wait_I2C();                        //Cho hoat dong I2C hoan tat

        // doc du lieu tu ROM va goi ra cong RS232
                _RSEN = 1;                        //Tao ra dieu kien START
                Wait_I2C();                        //Cho hoat dong I2C hoan tat
                //Buoc 2, ghi dia chi cua ROM, sap thao tac ghi vao ROM
                Write_I2C(0xA0);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi               
                Write_I2C(0x00);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
                Write_I2C(0x01);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
                _RSEN = 1;                        //Tao ra dieu kien RESTART
                Wait_I2C();                        //Cho hoat dong I2C hoan tat
                Write_I2C(0xA1);        //Ghi dia chi cua ROM, chuan bi doc tu ROM
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi

                temp = Read_I2C();
                _PEN=1;
                Wait_I2C();
                U1TXREG = temp;
                        while(!U1STAbits.TRMT); // cho hoan tat goi byte.       
                while(1) Nop();               
}

//Chuong trinh con khoi tao cac cong I/O
void Init_PORTS(void) {
        LATC = 0xFFFF;                //Tat cac LED (anode chung) noi vao cong E
        TRISC = 0;                //LED noi vao RC5
        TRISG=0;
}

//Chuong trinh con khoi tao module I2C
void Init_I2C(void) {
        I2CCON = 0x8200;                //bit15=I2CEN, bit9=DISSLW (tat Slew Rate
                                                        //Control cho cac toc do baud khac 400 kbps)
        I2CBRG = (((Fcy/baud) - (Fcy/1111111))-1);
}

//Chuong trinh con xuat 1 byte qua module I2C
void Write_I2C(unsigned char d) {
        I2CTRN = d;
}

//Chuong trinh con cho hoat dong 00Master I2C sau cung hoan tat
void Wait_I2C(void) {
        while (!_MI2CIF);
        _MI2CIF = 0;
}

//Chuong trinh con xu ly khi hoat dong I2C bi loi
void I2C_Fail(void) {
        _PEN = 1;                //Tao ra dieu kien STOP
        Wait_I2C();                        //Cho hoat dong I2C hoan tat
        LATC &= 0x0000;                //Bat LED noi vao RE0 de bao loi
        U1TXREG = 70;
        while (1);                        //Dung chuong trinh tai day
}
unsigned char Read_I2C(void) {
        unsigned char d;
        _RCEN = 1;                                //Cho phep nhan byte
        Wait_I2C();                                //Cho hoat dong I2C hoan tat
        d = I2CRCV;                                //Lay byte da nhan dat vao d
        _ACKEN = 1;                                //Ghi bit ACK/NACK ra I2C bus
        Wait_I2C();                                //Cho hoat dong I2C hoan tat
        return d;                                //Tra byte da doc ve chuong trinh goi
}

em xin lỗi vì code hơi dài, nhưng em không hiểu nó sai chỗ nào đành phải gởi lên cho mọi người xem giúp.
Các hàm đọc/ghi I2C em là tương tự TUT4 của anh namqn. Fcy của em là 7372800, baud của I2C = 100khz.
Các chân A0, A1, A2 của ROM em đã nối mass, nên địa chỉ của ROM là A0(ghi) và A1(đọc)
Module UART thì chắc ko sai, vì em đã thử các ví dụ khác, truyền và nhận rất tốt, tốc độ baud cũng ko sai, em đã kiểm tra kỹ, hơn nữa em nghi nếu sai tốc độ baud thì nó sẽ nhận được các ký tự lạ, đằng này không nhận được gì trên máy tính.
ROM thì chắc ko chết, vì em đã mua một con mới về thử :D.
Vậy có ai biết xin góp ý giúp em, hoặc có một ví dụ nào đó cụ thể về đọc ghi ROM 24c512 thì cho em xin để tham khảo, em cám ơn rất nhiều.

namqn 31-10-2009 07:47 AM

Không thể ghi vào 24C512 rồi đọc ra ngay đâu bạn, cần có khoảng 5 ms để EEPROM hoàn tất thao tác ghi. Sau khi chờ tối thiểu 5 ms, bạn tạo điều kiện START chứ không dùng RESTART được nhé.

Thân,

npbaoduy 31-10-2009 10:08 AM

Em đã thử rồi, sau khi ghi vào ROM, cho I2C stop, timer chạy, mỗi lần ngắt sau 0.5s mới start i2c và đọc từ rom, nhưng nó chỉ đọc được giá trị 0. Phần giao tiếp I2C thì ko báo lỗi, vì nếu báo lỗi, chương trình sẽ dừng khi vào hàm I2C_Fail(), đằng này chương trình vẫn chạy (có led nhấp nháy và cứ sau mỗi 0.5s đều gởi ra cổng nối tiếp giá trị 0).
Code:

void _ISR _T1Interrupt(void) {
        _T1IF = 0;                        //Xoa co ngat
        _LATC4 ^= 1;                //Lat trang thai LED
        _SEN = 1;                        //Tao ra dieu kien START
                Wait_I2C();                        //Cho hoat dong I2C hoan tat
               
                Write_I2C(0xA0);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
               
                Write_I2C(0x00);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
                Write_I2C(0x01);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
               
                _RSEN = 1;                        //Tao ra dieu kien RESTART
                Wait_I2C();                        //Cho hoat dong I2C hoan tat
               
                Write_I2C(0xA1);        //Ghi dia chi cua ROM, chuan bi doc tu ROM
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi

                temp = Read_I2C();
                _PEN=1;
                Wait_I2C();
                U1TXREG = temp;
                while (!U1STAbits.TRMT);
}

Nhân tiện đây em cũng xin hỏi, điều kiện start và restart khác nhau như thế nào?
Em xin cám ơn

namqn 31-10-2009 11:34 AM

Trích:

Nguyên văn bởi npbaoduy (Post 30753)
Em đã thử rồi, sau khi ghi vào ROM, cho I2C stop, timer chạy, mỗi lần ngắt sau 0.5s mới start i2c và đọc từ rom, nhưng nó chỉ đọc được giá trị 0. Phần giao tiếp I2C thì ko báo lỗi, vì nếu báo lỗi, chương trình sẽ dừng khi vào hàm I2C_Fail(), đằng này chương trình vẫn chạy (có led nhấp nháy và cứ sau mỗi 0.5s đều gởi ra cổng nối tiếp giá trị 0).
Code:

void _ISR _T1Interrupt(void) {
        _T1IF = 0;                        //Xoa co ngat
        _LATC4 ^= 1;                //Lat trang thai LED
        _SEN = 1;                        //Tao ra dieu kien START
                Wait_I2C();                        //Cho hoat dong I2C hoan tat
               
                Write_I2C(0xA0);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
               
                Write_I2C(0x00);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
                Write_I2C(0x01);
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi
               
                _RSEN = 1;                        //Tao ra dieu kien RESTART
                Wait_I2C();                        //Cho hoat dong I2C hoan tat
               
                Write_I2C(0xA1);        //Ghi dia chi cua ROM, chuan bi doc tu ROM
                if (_ACKSTAT)        I2C_Fail();                //Neu NACK thi xu ly loi

                temp = Read_I2C();
                _PEN=1;
                Wait_I2C();
                U1TXREG = temp;
                while (!U1STAbits.TRMT);
}

Nhân tiện đây em cũng xin hỏi, điều kiện start và restart khác nhau như thế nào?
Em xin cám ơn

Bạn nên thử với các tốc độ baud thấp, đừng thử với tốc độ tương đương tốc độ tối đa ghi trong datasheet của linh kiện.

START có đường truyền ở trạng thái idle đủ lâu, còn RESTART bao gồm STOP đi liền với START (tức là đường truyền không ở trạng thái idle đủ lâu như trường hợp START).

Thân,

npbaoduy 31-10-2009 01:15 PM

Cám ơn anh nhiều.
Nhưng em nghĩ tốc độ 100khz là nhỏ nhất rồi chứ? Trong datasheet em thấy có 1khz, 4khz và 1mhz lận :D.
Chắc em sẽ mua một con dsPIC mới về thử, biết đâu nó bị hư gì đấy, về sơ đồ kết nối thì em kiểm tra kỹ rồi, có điện trở 4.7k kéo lên nguồn nữa, loay hoay gần cả tuần mà vẫn chưa giải quyết được.
Nếu có ai đã từng giao tiếp với ROM này được, có thể cho em xin xem qua để tham khảo nhé.
Chúc mọi người vui vẻ.

harakiri 04-11-2009 01:36 PM

Em muốn gửi một loạt các chuỗi qua UART như "TC", delay 1 khoảng rồi gửi "RC m x y z k t" ( với m x y z k t là số thập phân) ,rồi "M". Tuy nhiên thanh ghi UxTXREG ( em dùng dsPIC33FJ64GP710) chỉ có 4 bộ đệm, như vậy em phải thiết lập thế nào các thanh ghi để gửi.

npbaoduy 08-11-2009 01:02 AM

điều gì xảy ra khi gởi giá trị 0 qua module UART?
 
Vấn đề ROM vẫn mò chưa ra :D, hôm nay em lại gặp một vấn đề thế này:
Code:

U1TXREG=0x00;
        while(!U1STAbits.TRMT);
        U1TXREG=0x41;
        while(!U1STAbits.TRMT);

thì trên máy tính chỉ nhận được giá trị 0, không nhận được 0x41 (ký tự A), em sử dụng VB, thấy không in ra được ký tự nào cả, dùng hàm lấy mã ascii chỉ thấy số 0.
còn nếu thay:
Code:

U1TXREG=0x01;  //có thể là một giá trị nào đó bất kỳ khác 0
        while(!U1STAbits.TRMT);
        U1TXREG=0x41;
        while(!U1STAbits.TRMT);

thì trên máy tính nhận được cả 2 giá trị (hiển thị được cả 2 ký tự).
Em không hiểu chỗ này, không lẽ khi gởi giá trị 0, bit U1STAbits.TRMT không được bật lên sau khi đã truyền xong hay sao?
Nếu thay bằng:
Code:

U1TXREG=0x00;
        delay_ms(100);
        U1TXREG=0x41;
        while(!U1STAbits.TRMT);

thì nhận được cả số 0 và số 0x41, nhưng điều kiện là delay_ms phải đủ lớn, nếu delay_ms(1) thì cũng ko nhận được số 0x41 (quan sát thấy y như trường hợp đầu tiên).

harakiri 11-11-2009 06:13 PM

Giả sử em nhận được về chip một chuỗi các kí tự " T a1 a2 a3 a4 a5"(a1,a2,a3... là số thập phân có 2 hoặc 3 chữ số nhưng bây giờ nó đang được xem là một chuỗi ký tự). Bây giờ em muốn tách chuỗi ký tự này thành một chuỗi a1 ,a2 ,a3....với a1,a2,a3 được xem là số. Liệu có hàm nào làm được điều này không?

mtuankct 11-11-2009 10:05 PM

Theo mình chẳng có hàm nào làm được cả, cái này do bạn tự quy định thôi mà, nó phụ thuộc vào dữ liệu của bạn. Đơn giản nhất theo mình là cứ quy định mỗi số chiếm 2 byte hoăc 3byte tùy bạn


Múi giờ GMT. Hiện tại là 03:49 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam