Các chân riêng lẻ của cổng khác nhau của vi điều khiển có thể được ánh xạ tới thanh ghi và giá trị của chúng có thể thay đổi khi thay đổi giá trị thanh ghi không?


12

Hỏi: Các chân riêng lẻ của các cổng khác nhau của bộ điều khiển vi mô có thể được ánh xạ tới một thanh ghi và giá trị của chúng có thể bị thay đổi khi thay đổi giá trị thanh ghi không?

Kịch bản: Tôi đã sử dụng hết một số chân từ mỗi cổng (8 bit) của bộ điều khiển vi mô. Bây giờ tôi muốn giao diện một thiết bị cần bus 8 bit (giả sử D0 đến D7 IN SEQUENCE) nghĩa là tôi cần 8 chân từ bộ điều khiển để tôi có thể kết nối chúng theo kiểu một-một

portx0  -> D0 // x is the name of port followed by bit location on that port
portx1  -> D1
...
portx7  -> D7

nhưng tôi không có toàn bộ cổng gồm 8 chân mà tôi có thể kết nối với thiết bị này, thay vào đó tôi có một số chân từ portx, một số từ porty và một số chân từ portz. Kịch bản kết nối mới là (kết nối từ bộ điều khiển vi đến thiết bị tương ứng)

portx0  -> D0
portx1  -> D1
portx2  -> D2
porty4  -> D3
porty5  -> D4
porty6  -> D5
porty7  -> D6
portz1  -> D7

Trong điều kiện này nếu tôi muốn gửi một giá trị nói

unsigned char dataReg = 0xFA;

đến thiết bị của tôi từ bộ điều khiển, tôi phải thực hiện các thao tác bit khôn ngoan trên giá trị được gửi và đặt từng pin theo giá trị trong thanh ghi riêng lẻ. Ví dụ

portx0 = ((dataReg & 0x01) >> 0 );  // Masking and shifting as bit position
portx1 = ((dataReg & 0x02) >> 1 );
portx2 = ((dataReg & 0x04) >> 2 );
porty4 = ((dataReg & 0x08) >> 3 );
porty5 = ((dataReg & 0x10) >> 4 );
porty6 = ((dataReg & 0x20) >> 5 );
porty7 = ((dataReg & 0x40) >> 6 );
portz1 = ((dataReg & 0x80) >> 7 );

Bây giờ, đến câu hỏi chính, để tránh các tính toán riêng lẻ này trên mỗi bit trên các cổng khác nhau, các chân riêng lẻ của các cổng khác nhau của bộ điều khiển vi mô có thể được ánh xạ tới một thanh ghi và thay đổi giá trị của chúng khi thay đổi giá trị thanh ghi không?


1
Tôi đã có cùng một ý tưởng trước đây. Với PIC, điều này là không thể: microchip.com/forums/tm.aspx?high=&m=696277 - Tôi không nghĩ rằng nó có thể với bất kỳ vi mô nào, nhưng liệt kê thiết bị của bạn sẽ hữu ích.

Câu trả lời:


6

Có vẻ như câu hỏi của bạn có một giá trị 8 bit trong phần sụn, và muốn đọc và viết nó từ và đến một bộ sưu tập các chân cổng tùy ý.

Không có cách phần cứng trực tiếp để làm điều này. Bạn phải viết hai thói quen, một để đọc giá trị 8 bit và một để viết nó. Những người khác đã đề cập đến việc sử dụng công đoàn, nhưng đó là một ý tưởng tồi. Với các hiệp hội, bạn phải xử lý từng bit một cách riêng biệt và mã trở nên phụ thuộc vào thứ tự bit của micro. Đây có thể là cách để đi nếu tất cả 8 bit được phân tán hoàn toàn độc lập. Nếu vậy, có rất ít bạn có thể làm nhưng để tạo mã đặc biệt cho mỗi bit.

Cách tốt hơn để làm điều này, đặc biệt là nếu bạn có thể nhóm các bit trong một vài đoạn liền kề trên các cổng vật lý là sử dụng mặt nạ, dịch chuyển và ORing. Ví dụ, nếu ba bit thấp của byte bên trong nằm trên các bit <6-4> của một cổng, thì phải dịch chuyển giá trị cổng đó bằng 4 và AND với 7 để đưa các bit đó vào vị trí cuối cùng. Dịch chuyển và mặt nạ (hoặc mặt nạ và dịch chuyển) các bit từ các cổng khác vào vị trí và lắp ráp byte 8 bit cuối cùng bằng cách OR kết quả vào đó.

Kiểu vặn bit mức thấp này dễ thực hiện hơn trong trình biên dịch chương trình so với C. Tôi có thể đặt các thói quen đọc và ghi byte trong một mô đun trình biên dịch mã đơn và làm cho giao diện có thể gọi được từ C.


6
Câu trả lời của tôi sẽ gần giống với câu trả lời của bạn, ngoại trừ việc tôi hoàn toàn không sử dụng lắp ráp; các thao tác bit là không đáng kể trong C. Tôi nghĩ rằng sẽ đau đầu hơn khi học quy ước gọi C cụ thể cho trình biên dịch và cách chạy trình liên kết. Phụ thuộc thực sự vào trình biên dịch và làm thế nào nó làm cho mọi thứ khó khăn. :-)
akohlsmith

@Andrew: Nghiêm túc chứ? Các quy ước gọi được viết rõ ràng trong bất kỳ hướng dẫn sử dụng trình biên dịch nào mà tôi đã thấy ở đó có thể cần phải giao tiếp với mã lắp ráp. Thao tác bit có thể là "tầm thường" để viết bằng C, nhưng đây là một lĩnh vực mà trình biên dịch có thể tạo ra mã khủng khiếp. Nếu tốc độ hoặc không gian mã không quan trọng, hãy sử dụng bất cứ thứ gì bạn thấy thoải mái hơn. Tôi cảm thấy thoải mái hơn với trình biên dịch mã cho việc vặn bit ở mức độ thấp, vì vậy tôi sẽ sử dụng nó. Nếu đây là một thói quen hạn chế tốc độ thấp, bạn nên thực hiện nó trong trình biên dịch chương trình. Nó thực sự nên được dễ dàng.
Olin Lathrop

1
Điều tôi đang nói là việc phải loay hoay với điều đó vì một việc tầm thường như thao túng bit không phải là điều tôi làm trừ khi có lý do rất chính đáng cho việc đó. Chúng tôi không biết chi tiết cụ thể về xe buýt song song của mình, nhưng hầu hết các xe buýt đều có tín hiệu nhấp nháy loại bỏ nhu cầu cập nhật "gần nguyên tử" của tất cả các chân xe buýt, do đó, việc lắp ráp có thể là tối ưu hóa không cần thiết và phức tạp không cần thiết (ngay cả khi đó là thẳng thắn).
akohlsmith

@Andrew: Nó chỉ đóng băng xung quanh hoặc phức tạp nếu bạn không biết bạn đang làm gì. Tôi nghĩ vấn đề thực sự là một số người sợ lắp ráp và không biết rõ về nó. Đó là một sai lầm. Nó cần phải là một công cụ sẵn sàng trong hộp công cụ của bạn. Nếu bạn không biết rõ về nó hoặc không thoải mái với nó, bạn sẽ luôn biện minh cho cách mọi thứ nên được thực hiện theo cách khác. Một số điều dễ dàng hơn trong trình biên dịch nếu bạn biết nó và HLL tốt như nhau. Hầu hết mọi người không, nhưng đó là một vấn đề với họ, không phải với việc sử dụng trình biên dịch chương trình.
Olin Lathrop

2
Tôi thành thạo ngôn ngữ lắp ráp trên một số bộ vi điều khiển / bộ vi xử lý. Tôi không đồng ý rằng nó phải là một công cụ sẵn sàng; nó nên được sử dụng một cách tiết kiệm và chỉ khi cần thiết, thường là cho việc khởi tạo ở mức rất thấp, mã thời gian hoặc kích thước quan trọng hoặc trong trường hợp phổ biến hơn, tối ưu hóa một khu vực bạn đã xác định là một nút cổ chai. Tôi thấy rằng các dự án nơi các tác giả nhảy vào lắp ráp bởi vì nó thường viết mã ít rõ ràng hơn hoặc không nhận ra khi thuật toán bị áp dụng sai. Tôi không nói cụ thể đó là bạn, mà là trong trường hợp tổng quát hơn.
akohlsmith

4

Nói chung điều này là không thể. Theo như tôi biết, điều đó là không thể với PIC.

Chỉ có một vi điều khiển mà tôi biết có thể làm điều này, đó là Cypress PSoC . Đây là một hệ thống cấu hình cao trên chip. Trong số nhiều việc, nó cho phép bạn làm là xác định đúng nghĩa đen của thanh ghi của riêng bạn (1-8 bit) và kết nối nó với bất kỳ chân nào bạn thích, hoặc thậm chí với các mạch bên trong.

Dây điện PSoC

Ví dụ, ở đây tôi đã tạo ra một thanh ghi điều khiển 6 bit. 5 trong số các bit đi thẳng đến các chân, trong khi bit thứ 6 tôi đang sử dụng cho XOR với đầu vào từ chân thứ 7.

Chân PSoC

Trên chip, tôi có thể chọn phân bổ các chân này cho bất kỳ chân GPIO nào có sẵn. (Đó là những màu xám một trong những hình ảnh)


1
LPC800 cũng có thể làm điều đó, vì các chức năng có thể được gán tự do cho các chân.
starblue

-1

Bạn có thể thử như sau. Viết cấu trúc của riêng bạn ánh xạ tới các chân tương ứng của 2 cổng (sẽ được sử dụng) Bây giờ cập nhật giá trị trong thanh ghi này sẽ đặt / đặt lại các chân của 2 cổng đó. Chỉ cần thử và cho chúng tôi biết nếu nó hoạt động !!

Tôi tự tin điều này nên làm việc.


2
Trong C, bạn có thể ánh xạ cấu trúc đến một vị trí bộ nhớ và bạn có thể ánh xạ các bit của cấu trúc của mình (các trường bit) sang các bit bit, nhưng không có cách nào để ngăn trình biên dịch làm rối với các bit 'inb between', và hiện tại đã có cách để xem cấu trúc 'tổng thể' một giá trị số nguyên duy nhất. Điều này sẽ không làm việc.
Wouter van Ooijen

-1

Nếu tôi hiểu chính xác câu hỏi, nó đủ dễ trong C:

Khai báo kiểu chung, có thể được sử dụng lại cho bất kỳ đăng ký nào:

typedef union    // Generic 8-bit register Type
{
  uint8 reg; // Whole register
  struct
  {
    unsigned  bit7     : 1;  // Bit 7 
    unsigned  bit6     : 1;  // Bit 6 
    unsigned  bit5     : 1;  // Bit 5 
    unsigned  bit4     : 1;  // Bit 4 
    unsigned  bit3     : 1;  // Bit 3 
    unsigned  bit2     : 1;  // Bit 2 
    unsigned  bit1     : 1;  // Bit 1 
    unsigned  bit0     : 1;  // Bit 0 
  } bit;
} typ_GENERIC_REG8;

Vì vậy, để xác định một cổng chúng tôi muốn giải quyết:

#define MCU_GPO_PORTx   (*(volatile typ_GENERIC_REG8 *)(0x12345678)) // Number is address

Và để trực tiếp xoay một pin trên cổng đó:

#define MCU_PORTx_PINn  (MCU_GPO_PORTx.bit.bit0)

Trong mã:

MCU_PORTx_PINn = 1; // Set pin high

Toàn bộ đăng ký:

MCU_GPO_PORTx.reg = 0xF; // All pins high

Rất đáng để đọc lên các cấu trúc, công đoàn, typedefs và enum - tất cả những điều này làm cho cuộc sống tốt đẹp hơn rất nhiều trong nhúng & nói chung!


OP muốn kết hợp một số bit từ các cổng khác nhau thành 'một byte'. Tôi không thấy làm thế nào điều này sẽ làm điều đó? Olin Lathrop giải thích lý do tại sao điều đó là không thể.

Điều này thực sự không giải quyết được vấn đề và tùy thuộc vào mức độ "smrt" trình biên dịch của bạn, có thể tạo ra một loạt các rắc rối mới để gỡ lỗi.
akohlsmith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.