마이크로 컨트롤러의 다른 포트의 개별 핀을 레지스터에 매핑 할 수 있고 레지스터 값을 변경할 때 해당 값을 변경할 수 있습니까?


12

Q : 마이크로 컨트롤러의 다른 포트의 개별 핀을 레지스터에 매핑 할 수 있고 레지스터 값을 변경할 때 해당 값이 변경 될 수 있습니까?

시나리오 : 마이크로 컨트롤러의 각 포트 (8 비트)에서 일부 핀을 사용했습니다. 이제 8 비트 버스 (D0 ~ D7 IN SEQUENCE 제공)가 필요한 장치를 인터페이스하고 싶습니다. 즉, 컨트롤러에서 8 핀이 필요하므로 일대일 방식으로 연결할 수 있습니다

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

그러나 나는이 장치에 연결할 수있는 8 핀의 전체 포트가 없지만 portx의 일부 핀, porty의 일부 핀 및 portz의 일부 핀이 있습니다. 새로운 연결 시나리오는 다음과 같습니다 (각각 마이크로 컨트롤러에서 장치로 연결)

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

이 조건에서 값을 보내려면

unsigned char dataReg = 0xFA;

컨트롤러에서 내 장치로 보낼 값에 대해 비트 단위 작업을 수행하고 레지스터의 값에 따라 각 핀을 개별적으로 설정해야합니다. 예를 들어

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 );

이제 주요 질문으로 다른 포트의 각 비트에서 이러한 개별 계산을 피하기 위해 마이크로 컨트롤러의 다른 포트의 개별 핀을 레지스터에 매핑하고 레지스터 값을 변경할 때 해당 값을 변경할 수 있습니까?


1
나는 얼마 전에 같은 생각을 가지고 있었다. PIC를 사용하면 불가능합니다 : microchip.com/forums/tm.aspx?high=&m=696277-마이크로 에서는 가능 하지 않다고 생각하지만 장치를 나열하면 도움이됩니다.

답변:


6

귀하의 질문은 펌웨어에 8 비트 값이 있고 임의의 포트 핀 모음에서 읽고 쓰기를 원한다는 것입니다.

이를 수행하는 직접적인 하드웨어 방법은 없습니다. 하나는 8 비트 값을 읽고 다른 하나는 2 개의 루틴을 작성해야합니다. 다른 사람들은 노조 사용에 대해 언급했지만 나쁜 생각입니다. 공용체를 사용하면 모든 비트를 개별적으로 처리해야하며 코드는 마이크로의 비트 순서에 따라 달라집니다. 8 비트가 모두 완전히 독립적으로 흩어져 있다면 어쨌든 갈 수 있습니다. 그렇다면 각 비트마다 특별한 코드를 만드는 것 외에는 할 수있는 일이 거의 없습니다.

물리적 포트에서 몇 개의 연속 된 청크로 비트를 그룹화 할 수있는 경우이를 수행하는 더 좋은 방법은 마스킹, 시프트 및 ORing을 사용하는 것입니다. 예를 들어, 내부 바이트의 하위 3 비트가 포트의 비트 <6-4>에있는 경우 해당 포트 값을 4만큼 오른쪽으로 시프트하고 7로 비트를 이동하여 해당 비트를 최종 위치로 가져옵니다. 다른 포트에서 비트를 이동 및 마스크 (또는 마스크 및 이동)하고 결과를 OR로 연결하여 최종 8 비트 바이트를 어셈블합니다.

이런 종류의 저수준 비트 트위들 링은 C보다 어셈블러에서 수행하기가 더 쉽습니다. 아마도 바이트 읽기 및 쓰기 루틴을 단일 어셈블러 모듈에 넣고 인터페이스를 C에서 호출 할 수있게 만들 것입니다.


6
내 대답은 어셈블리를 전혀 사용하지 않는다는 점을 제외하고는 거의 동일합니다. 비트 조작은 C에서 사소한 것입니다. 컴파일러에 대한 특정 C 호출 규칙과 링커를 실행하는 방법을 배우는 데 더 어려움이 있다고 생각합니다. 실제로 컴파일러에 따라 달라집니다. :-)
akohlsmith 2013

@Andrew : 정말요? 호출 규칙은 어셈블리 코드와 인터페이스해야 할 위치를 보았던 컴파일러 매뉴얼에서 명확하게 설명되어 있습니다. 비트 조작은 C로 작성하는 것이 "사소한"것일 수 있지만, 이것은 컴파일러가 끔찍한 코드를 생성 할 수있는 영역입니다. 속도 나 코드 공간이 중요하지 않으면 더 편한 것을 사용하십시오. 낮은 수준의 비트 트위들 링을 위해 어셈블러에 더 익숙하므로 사용하겠습니다. 이것이 낮은 수준의 속도 임계 루틴 인 경우 어셈블러에서 수행해야합니다. 정말 쉬워야합니다.
Olin Lathrop

1
내가 말하고있는 것은 비트 조작과 같은 사소한 일을 위해 그 주위를 두는 것이 좋은 이유가 없다면 내가 할 일이 아니라는 것입니다. 우리는 병렬 버스의 특성을 알지 못하지만 대부분의 버스에는 모든 버스 핀의 "원자력"업데이트가 필요하지 않은 스트로브 신호가 있으므로 어셈블리로 떨어 뜨리는 것은 불필요한 최적화와 불필요한 복잡성 일 수 있습니다. 똑바로).
akohlsmith

@Andrew : 현재하고있는 일을 모르는 경우에만 주위를 어지럽히거나 복잡하게 만듭니다. 실제 문제는 일부 사람들이 어셈블러를 두려워하고 그것을 잘 모른다는 것입니다. 그건 실수 야 도구 상자에 준비된 도구 여야합니다. 잘 모르거나 불편한 경우 다른 방법으로 일을 처리하는 방법을 항상 정당화해야합니다. 어떤 것들은는 쉽게 당신이 그것을하고 HLL 똑같이 잘 알고있는 경우 어셈블러있다. 대부분의 사람들은 그렇지 않지만 어셈블러를 사용하는 것이 아니라 문제가 있습니다.
Olin Lathrop

2
여러 마이크로 컨트롤러 / 마이크로 프로세서에서 어셈블리 언어에 정통합니다. 나는 그것이 준비된 도구 여야한다는 것에 동의하지 않는다. 일반적으로 매우 낮은 수준의 초기화, 타이밍 또는 크기에 중요한 코드 또는보다 일반적인 경우 병목 현상이 발생한 것으로 판단 된 영역의 최적화를 위해 필요할 때만 드물게 사용해야합니다. 어셈블리가 너무 까다로워 져서 알고리즘이 잘못 적용되는 시점을 인식하지 못하는 경우가 많으므로 어셈블리로 이동하는 프로젝트를 발견했습니다. 나는 그것이 당신이라고 구체적으로 말하는 것이 아니라보다 일반적인 경우입니다.
akohlsmith

4

일반적으로 불가능합니다. 내가 아는 한 PIC로는 불가능합니다.

이 작업을 수행 할 수있는 마이크로 컨트롤러는 Cypress PSoC 뿐입니다 . 고도로 구성 가능한 시스템 온 칩입니다. 그것은 당신이 할 수있는 많은 것들을 문자 그대로 자신의 레지스터 (1-8 비트)를 정의하고 좋아하는 핀 또는 내부 회로에 연결하는 것입니다.

PSoC 배선

예를 들어, 여기 6 비트 제어 레지스터를 만들었습니다. 비트 중 5 개는 곧바로 핀으로 이동하고 6 번째 비트는 7 번째 핀의 입력으로 XOR에 사용합니다.

PSoC 핀

칩에서 이러한 핀을 사용 가능한 GPIO 핀 중 하나에 할당하도록 선택할 수 있습니다. (이미지는 회색입니다)


1
LPC800은 핀에 기능을 자유롭게 할당 할 수 있기 때문에 가능합니다.
starblue

-1

다음을 시도해보십시오. 2 개의 포트 (각 포트)의 각 핀에 대응하는 구조를 작성하십시오. 이제이 레지스터의 값을 업데이트하면 2 포트의 핀을 설정 / 재설정해야합니다. 그냥 작동하는지 알려주십시오!

이것이 효과가 있다고 확신합니다.


2
C에서는 구조체를 메모리 위치에 매핑 할 수 있고 구조체의 비트 (비트 필드)를 비트 오프셋에 매핑 할 수 있지만 컴파일러가 'inbetween'비트를 엉망으로 만드는 것을 막을 방법이 없습니다. '전체'구조를 단일 정수 값으로 보는 방법. 작동하지 않습니다.
Wouter van Ooijen

-1

질문을 올바르게 이해했다면 C에서 충분히 쉽습니다.

일반 유형 선언은 모든 레지스터에 재사용 할 수 있습니다.

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;

따라서 포트를 정의하려면 다음을 수행하십시오.

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

그리고 그 포트에서 직접 핀을 돌리기 위해서 :

#define MCU_PORTx_PINn  (MCU_GPO_PORTx.bit.bit0)

코드에서 :

MCU_PORTx_PINn = 1; // Set pin high

전체 레지스터 :

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

구조체, 공용체, typedef 및 열거 형에 대해 읽을 가치가 있습니다.이 모든 것이 임베디드 및 일반적으로 삶을 훨씬 더 멋지게 만듭니다!


OP는 다른 포트의 여러 비트를 '1 바이트'로 결합하려고합니다. 어떻게 그렇게되는지 모르겠어요? Olin Lathrop 이 불가능한 이유를 설명 합니다.

이것은 실제로이 문제를 해결하지는 않으며, 컴파일러의 "smrt"에 따라 완전히 새로운 디버그 문제가 발생할 수 있습니다.
akohlsmith 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.