Nếu đây là lần đầu tiên đến với Điện Tử Việt Nam, bạn có thể đọc phần Hỏi đáp bằng cách nhấn vào liên kết. Có thể bạn cần đăng kí trước khi có thể gửi bài . Để bắt đầu xem bài viết, chọn diễn đàn bạn muốn thăm dưới đây.
XIN MỌI NGƯỜI GIÚP ĐỠ ,GIẢI THÍCH GIÙM LỆNH NÀY VỚI.CẢM ƠN NHIỀU
*(((char*)&block_number)+3)
tôi đoán ý bạn là bạn không hiểu kiểu dữ liệu được gán cho biến được trình bày như trên đúng không?
Đây là cách để ép kiểu dữ liệu. Cũng khá lằng nhằng nhưng hãy phân tích từ từ ra.
///////////
xét trường hợp đơn giản hơn là thế này: giả sử bạn khai báo
char* c;
int16* p;
int16 a;
char b;
b= *c;
a=*p;
//giá trị được trỏ bởi biến con trỏ c là giá trị 8 bit.
//giá trị được trỏ bởi biến con trỏ p là giá trị 16 bit;
sẽ không hợp lệ nếu bạn viết: b=*p;
để lấy giá trị 8 bit trỏ từ con trỏ p bạn phải làm thế này:
b=*((char*)p);
//////////
giờ đến trường hợp gần với câu hỏi của bạn nhất nhe: hãy xem a và b khác nhau như thế nào nhé
int16 block_number; //block_number là giá trị 16 bít
int16 a; // a la bien 16bit
char b; //b la bien 8 bit
block_number=0x05af;
a=*(&block_number) //
b=*((char *)&block_number)
kết quả là: a=0x05af;
b=0xaf;
///
Tôi đoán không nhầm thì bài toán của bạn sử dụng trong hoàn cảnh lấy các dữ liệu 8bit từ một array mà phần tủ lớn hơn 8 bit,
vd int16 block_number[10];
Hi vọng bạn hiểu!
lệnh mình dùng cụ thể trong hàm sau:
char mmc_open_block(int32 block_number){
block_number*=512;
SS=0; // set SS = 0 (on)
SPI_WRITE(0x51); // send mmc read single block command
SPI_WRITE(*(((char*)&block_number)+3)); // arguments are address
SPI_WRITE(*(((char*)&block_number)+2));
SPI_WRITE(*(((char*)&block_number)+1));
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1; // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
if((mmc_response(0xFE))==1) return 1; // wait for data token
return(0);
}
NẾU block_number là 2 thì số phải điền vào 4 BYTE của 4 hàm SPI_WRITE () chính giữa là số 512 tức là 0X200 và lần lượt các byte :0x00;0x00;0x02;0x00
nếu block thứ 3 thi điền vào số 1024=0x400 và 4 byte phải điền là 0x00;0x00;0x04;0x00
BẠN PUMA CÓ THỂ GIẢI THÍCH GIÙM MÌNH KHÔNG?CẢM ƠN BẠN NHIỀU.
lệnh mình dùng cụ thể trong hàm sau:
char mmc_open_block(int32 block_number){
block_number*=512;
SS=0; // set SS = 0 (on)
SPI_WRITE(0x51); // send mmc read single block command
SPI_WRITE(*(((char*)&block_number)+3)); // arguments are address
SPI_WRITE(*(((char*)&block_number)+2));
SPI_WRITE(*(((char*)&block_number)+1));
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1; // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
if((mmc_response(0xFE))==1) return 1; // wait for data token
return(0);
}
NẾU block_number là 2 thì số phải điền vào 4 BYTE của 4 hàm SPI_WRITE () chính giữa là số 512 tức là 0X200 và lần lượt các byte :0x00;0x00;0x02;0x00
nếu block thứ 3 thi điền vào số 1024=0x400 và 4 byte phải điền là 0x00;0x00;0x04;0x00
BẠN PUMA CÓ THỂ GIẢI THÍCH GIÙM MÌNH KHÔNG?CẢM ƠN BẠN NHIỀU.
//////////////
khi bạn khai báo 1 biến 16 bit hoặc 32 bit thì trình dịch CCS nó sẽ sắp xếp địa chỉ theo thứ tự tăng dần ứng với byte thấp nhất đến byte cao nhất.
//////////////
như vậy với các lệnh:
SPI_WRITE(*(((char*)&block_number)+3)); // arguments are address
SPI_WRITE(*(((char*)&block_number)+2));
SPI_WRITE(*(((char*)&block_number)+1));
SPI_WRITE(*((char*)&block_number)); ////////////////////////////
/////
Có nghĩa là ghi các byte từ cao nhất đến thấp nhất của block_number;
Với block_number = 512 thì sắp sếp theo thứ tự tăng dần trong bộ nhớ sẽ là 0x00 0x02 0x00 0x00
Với block_number =2 thì sắp sếp theo thứ tự tăng dần trong bộ nhớ sẽ là 0x02 0x00 0x00 0x00
/// bạn chú ý là bố trí theo thứ tự tăng dần trong bộ nhớ nó ngược với khi biểu diễn giá trị hexa nhé, khi biểu diễn 1 giá trị theo hexa:
512 = 0x00 00 02 00 ;
2 = 0x00 00 00 02 ;
////////////////////////////////////////////
vấn đề của bạn là: với biến block_number là biến 32 bit, nếu bạn không trình bày ép kiểu (char*) thì để lấy ra từng byte thì bạn sẽ không bao giờ lấy được từng byte của biến 32bit.
giải thích nhé: giả sử biến block_number được bố trí bắt đầu từ địa chỉ 100 trong RAM (tùy loại VDK mà bố trí trong vùng RAM nào để thao tác, cái này viết ASM hoặc MPLAB C sẽ rõ, ở CCS thì nó tự động làm). Lúc này trình dịch sẽ bố trí địa chỉ như sau:
&block_number = 100; và (&block_number + 1) = 104; và (&block_number + 2) = 108
Do đó nếu bạn *(&bock_number + 1) có nghĩa là bạn sẽ lấy dữ liệu từ địa chỉ 104;
nhưng viết *(((char*)&block_number) + 1) có nghĩa bạn sẽ lấy dữ liệu từ địa chỉ 101;
Hi vọng bạn hiểu được vấn đề!
Với CCS thì như vậy chứ ở MPLAB C thì nó chặt chẽ hơn trong việc khai báo bố trí bộ nhớ cho các biến.
Dạ, cảm ơn bác đã nghe qua và có lời khích lệ cháu ạ.
Thật lòng cháu không dám nhận hai danh hiệu Kỹ sư và Nhạc sĩ đâu ạ, vì phải thật hiểu sâu nắm vững cơ, chứ thực lực cháu đây chỉ là biết chút ít thôi à. Về phần...
Như tiêu đề, các bác giới thiệu e mạch sạc nlmt mppt có chức năng chỉnh dòng với, tấm PV của em 18V 55W, dùng để sạc cho khối pin sắt 3.2V 45A (sắp tới sẽ thay bằng ắc quy 12V)
e cảm ơn
Comment