페이지

글목록

2016년 1월 20일 수요일

[PSOC] I2C 통신시에 FIFO 초기화 문제(PSOC4)

안녕하세요, 오랜만입니다.

이번 이슈는 PSOC4 에서 I2C 통신을 하다가, I2CMasterWriteBuf() 함수를 사용할 경우 잘못된 SUB ADDRESS에 데이터를 송신하면 송신한 데이터들이 내부 FIFO 버퍼에 쌓여있다가 정상적인 SUB ADDRESS에 다시 데이터를 쓸 경우 이전에 쌓여있는 데이터가 출력되는 것을 발견했습니다.

이 문제의 발생빈도는 on-chip program 시에는 50% 정도이지만, 디버그 모드에서는 80%이상이었습니다. 즉 항상 발생하는 것은 아니라는 것이지만, 문제가 되기에는 충분합니다.

현재 Cypress에 기술 문의를 요청한 상태이고 빨리 해결되었으면 좋겠네요.

항상 제대로된 어드레스에 데이터를 전송하는 것은 아니라, 이런 경우도 있다는 점을 업체에서 인지하지 못했던 것 같습니다.

[PSOC] PSOC5LP(CY8C5268) 에 USB UART 연결 테스트

안녕하세요, 이번에는 USB UART(VCOM) 을 다뤄 보려 합니다.
USB는 쓰기 어려울 거라 생각하고, 계속 안쓰다가 이번에 더이상 확장할 통신 포트가 없어서 에라 모르겠다하고 하드웨어를 설계해 버렸습니다.

그런데 써보니 정말 좋습니다. 오늘 하루 몇시간 만에, USB UART 와 USB Bootloader , USB Bootloaderble App 까지 테스트를 다 해봤습니다.

테스트는 간단하게 끝났지만, 여기에 글을 올리는 시간이 몇배는 더 걸리는 것 같습니다.

일단은 첫번째로 USB UART 테스트에 관한 글을 올려봅니다.

먼저 PSOC 중에서 USB가 있는 MCU를 준비합니다. 
저는 PSOC-5LP 계열의 MCU를 준비했습니다.
물론 USB 콘넥터를 제대로 연결해야 겠지요. +5V, GND, DM, DP 를 USB 케이블에 연결해 둡니다.

[USB cable 연결]



[PSOC-5LP 의 USB 연결 회로도]


이렇게 USB 케이블을 연결했으면 일단 컴퓨터의 USB 포트에 꼽아 두십시요. 꼽으면 USB 포트로부터 +5V를 받아서 PSOC이나 ㄷ다른 IC에 공급할 3.3V 전원도 LDO 레귤레이터에 의해서 공급됩니다.

그럼 다음으로 USB UART 예제 프로그램을 불러와서 프로젝트를 만들어 보겠습니다.



우선 다음 그림과 같이 File-New-Project 순으로 클릭하시면 프로젝트 만들기 메뉴가 나옵니다.


개발키트로 테스트 하는 것이 아니고 회사 프로젝트로 만든 보드로 테스트 하는 것이므로 다음 그림과 같이 Target device 를 선택합니다.


다음으로 코드 예제를 import 할 것이므로 Code Example을 선택하고 Next로 갑니다.



코드 예제가 너무 많으므로 usb 로 검색을 해보면, USB UART 예제가 있으니 선택하고 Next로 갑니다.



필요시에 폴더를 새로 만들거나 지정해서 프로젝트 만들기를 마무리 합니다.




자, 이제 프로젝트가 만들어 졌네요. ^^.


그런데, 제게는 LCD가 없네요. TopDesign.cysch 에서 LCD 삭제합니다.





그런데, PSOC-5LP로 프로젝트를 만들면 기본으로 제가 쓰는 PSOC 모델이 아닌 것이 선택되네요. 그래서 project-Device select 메뉴에서 적당한 PSOC-5LP 장치를 선택합니다.

아... 이런, 옆에 Resource Meter는 컴파일을 다 해야지만 결과가 나오는데, 먼저 붙여 버렸네요. 이 그림을 붙여 넣은 이유는 USB UART 를 사용하는데 UDB가 전혀 안들어간다는 사실을 알려 드리기 위함입니다. 그냥 아주 좋은 통신 포트를 공으로 1개 얻었다 생각하시면 됩니다. ^^


[PSOC Device Select]



다음으로는 아까 LCD 콤포넌트를 지웠기 때문에 예제 소스 코드에 남아있는 LCD 관련 코드에서 컴파일 시에 에러가 날겁니다.
예러를 없애야 하는데, 이상태로 컴파일을 해버립시다. 그러면 에러가 나죠?


다음처럼 에러가 난 부분을 // 로 주석처리해서 다 막아버리세요.


그리고 나서 다시 컴파일을 하면 에러가 싹 사라지고, 에러 없이 컴파일이 완료 됩니다.
에러가 없으므로 3번 프로그래밍 아이콘 버튼을 눌러 프로그램을 PSOC에 다운로드 합니다.
물론 JTAG를 연결한 상태로 하셔야겠죠. ^^



다운로드 되면 바로 프로그램이 실행 되는데, 띠용 소리 나면서 디바이스 드라이버를 자동으로 찾아서 가상 시리얼 포트가 잡힙니다.
Cypress USB UART(COM24) 로 잡혔군요. 프로그램 잘 동작하는 것 같습니다. ^^



어떤 때는, 드라이버가 자동으로 안잡히는 분들이 있을 겁니다. 이 때는, " C:\Program Files (x86)\Cypress " 경로로 드라이버 찾기를 지정해 주면 알아서 찾아 깔아 주고 USB UART 가 잡힐 것입니다.


이 프로그램은 Rxd 로 데이터를 받으면 Txd로 그대로 ECHO 해 주는 프로그램이라서, 터미날을 1개 열어서 해당 COM PORT에 연결한 후, 데이터를 보내보면 에코로 돌아오는 것을 볼 수 있습니다. 예... 프로그램 아주 잘 돌아가고 있네요.


또 하나, USB 니까 속도도 빠르겠죠? TERA TERM 터미날 프로그램의 최대 속도인 921.6Kbps로 설정을 바꿔봤습니다.



데이터를 키보드로 두드려서 보냈더니 echo가 제대로 오는 것을 볼 수 있네요.
^^ 당신은 거의 1Mbps 속도의 UART를 득템하셨습니다.

2016년 1월 6일 수요일

[PSOC] Psoc4 GPIO INPUT (IN/OUT Test 2/2)

이번에는 입력 테스트를 해 보겠습니다.

1. 먼저 Digital Input Pin [v2.10] 콤포넌트를 선택해서 cysch 파일에 넣습니다.
이름은 적당히 지어 줍니다. 저는 SW_IN_1,SW_IN_2,SW_IN_3 이라고 지었고, 나중에 컴파일하면 자동으로 입력함수인 SW_IN_1_Read() ,SW_IN_2_Read() ,SW_IN_3_Read() 함수가 생깁니다.


2. 입력 핀 설정 중에서 , HW connection 옵션을 제거합니다.
또한 핀 Drive mode 에서 resistive pullup으로 내부 풀업을 걸어 줍니다.


3. cydwr 파일에서 핀을 회로도에 맞게 지정을 해 줍니다.


PSOC4 IC 의 입력핀 회로도와 이에 연결된 SW 회로도 첨부합니다.


5. 이제 컴파일을 하면 자동으로 SW_IN_x_Read() 함수가 생기는데 이것을 사용해서 포트값을 읽으면 됩니다.
코드의 예는 다음과 같습니다.
    for(;;)
    {
        if (f_50ms)
        {
            f_50ms = 0;
            sw_stat_old = sw_stat_new;
            sw_stat_new = (((SW_IN_1_Read()<<0 b="" ead="" x07="">
           
            if (sw_stat_new != sw_stat_old)
            {
                UART_1_UartPutString("switch stat = ");
                ser_tx_buf[0] = htoa(sw_stat_new);
                ser_tx_buf[1] = '\n';
                ser_tx_buf[2] = '\r';
                ser_tx_buf[3] = '\0';
                user_UART_PutString(ser_tx_buf);
            }
        }
        /* Place your application code here. */
    }

2016년 1월 5일 화요일

[PSOC] Psoc4 GPIO OUTPUT (IN/OUT Test 1/2)

PSOC4 에서의 GPIO IN/OUT TEST

이전 게시물에서 LED를 사용하는 GPIO OUT을 이미 테스트 했는데,
아무 설명을 하지 못해서 INPUT 테스트와 같이 다뤄 보겠습니다.

PSOC IC에 SW를 3개 달아서, 이전에 만들어 놓았던 타이머 인터럽트를 이용해서 50ms 마다 Switch 입력을 읽어서 값이 바뀔 때마다 스위치 값을 UART로 출력하는 내용입니다.

GPIO 출력은 이전에 해뒀던 내용인데, 100ms 마다 포트값을 토글하는 내용입니다.

먼저 OUTPUT을 설명드리겠습니다.

1. PSOC Creator 의 cysch 에서 Digital Output Pin [v2.10] 콤포넌트를 그려 넣습니다. 핀 이름은 적당하게 고치면 되는데 이름에 따라 함수가 자동으로 만들어집니다.
저는 LED_1,LED_2,LED_3 라고 정했는데, 출력 함수 이름은 자동으로 LED_1_Write() , LED_2_Write() , LED_3_Write() 으로 만들어 집니다.


2. OUTPUT PIN 콤포넌트를 마우스로 더블클릭하면 핀 설정이 나오는데, HW connection 체크를 해제 해 주십시요. 이것은 내부에서 다른 콤포넌트와 연결 하지 않을 경우에 해당되며, 이 옵션을 해제하지 않으면 에러가 납니다.

3. cydwr 파일에서 PSOC4 IC에 OUTPUT으로 사용할 핀을 지정

PSOC4 IC 와 연결된 출력 핀과 여기에 연결된 LED 회로도 그림을 아래 첨부합니다.



4. 소스 코드에서 포트 이름에 따라 자동 생성된 LED_x.c 안의 LED_x_Write() 함수로 비트를 ON(1),OFF(0) 하면 됩니다.

이전에 만든 타이머 인터럽트 코드 안에 있는 출력함수 예는 다음과 같습니다.

CY_ISR(Timer_INT_Handler)
{

    uint32 InterruptHpn;
    static uint8_t LED_1_stat=0,LED_2_stat=0,LED_3_stat=0;
    /* Check interrupt source and clear Inerrupt */
    InterruptHpn = Timer_1_GetInterruptSourceMasked();
    if (InterruptHpn == Timer_1_INTR_MASK_CC_MATCH)
    {
        Timer_1_ClearInterrupt(Timer_1_INTR_MASK_CC_MATCH);
    }
    else
    {
        cnt_50ms++;
        if (cnt_50ms > 49)
        {
            f_50ms = 1;
        }
        LED_1_stat = 1-LED_1_stat;
        LED_2_stat = 1-LED_2_stat;
        LED_3_stat = 1-LED_3_stat;
        LED_1_Write(LED_1_stat);
        LED_2_Write(LED_2_stat);
        LED_3_Write(LED_3_stat);
        Timer_1_ClearInterrupt(Timer_1_INTR_MASK_TC);
    }
}

[PSOC] PSOC4 Timer Interrupt Test

PSOC4 로 Timer Interrupt 를 회사에서 만든 보드로 테스트를 해 봤습니다.

역시 PSOC은 쉽네요.^^

UART는 기본으로 넣었고, 나중에 추가할 I2C도 일단은 H/W 콤포넌트로 추가했습니다.
PSOC4는 UART,SPI,I2C 등의 Serial 통신 모듈은 3 중에 1개를 써도, Serial 통신 모듈 총 2개 중 1개씩 감소합니다. 물론 UDB로 더 만들 수 있지만 UDB가 많이 들어갑니다.
저는 UART 1개, I2C 1개 기본 serial 통신 모듈을 2개 다 사용했네요.

PSOC4에서 타이머 인터럽트 사용하는 내용이 카페에 없어서, 자료를 만들어서 놓습니다.

프로그램시 타이머는 기본으로 사용하는 요소지요.

PSOC4는 타이머를 기본으로 4개를 지원합니다. 더 필요하면 UDB를 사용해서 만들어 넣으면 되는데, UDB가 4개 밖에 없어서 꼭 필요할 때를 위해서 아껴서 쓰는 것이 좋습니다.


<프로그램 테스트 계획>
- 타이머 인터럽트에 의해 주기적(100ms)으로 LED를 토글함.


1. 먼저 TopDesign.cysch 파일에 UART,I2C,Timer 콤포넌트를 추가합니다.


안보여서, 콤포넌트 쪽을 자세히 볼 수 있는 그림을 올립니다.

PSOC Creator 에서 컴파일을 해 보면 우측 옆 태에 Resource Meter를 보면 메모리나 콤포넌트, UDB 의 사용량이 나옵니다.


2. 다음은 Timer 의 설정입니다.
10KHz 의 클럭을 넣었으니 1 주기를 100ms로 맞출려면 1000 번 카운트해야 하므로 Timer 콤포넌트의 period 를 1000으로 수정합니다.

3. Interrupt 는 On terminal count 에 체크하는데, 타이머 끝에서 Interrupt가 발생된다는 의미입니다. Run Mode 는 Continuous 로 계속 반복됩니다. (위 그림 보시면 이해 되겠죠?)

4. System 의 Interrupt 콤포넌트를 Timer Interrupt 출력에 붙입니다.

5. 핀을 회로도에 맞게 지정합니다.
제가 사용하는 보드에는 PSOC4와 다음과 같이 연결되어 있습니다.

- UART RxD=P.4 , TxD=P0.5
- I2C SCL=P4.0 , SDA=P4.1
- LED_1=P2.4 , LED_2=P2.5 , LED_3=P2.6

[회로도] - 잘 안보이지만 연결은 위의 내용처럼 되어 있습니다.

cydwr 파일에서 핀을 위의 내용 처럼 지정합니다.



여기까지 H/W 구성은 마무리 되었습니다.

6. 이제 프로그램을 수정합시다.
먼저 Main() 함수에서 Timer 인터럽트 함수를 지정합니다. 나중에 설정된 주기마다, 이 인터럽트 함수가 실행됩니다.
    /* Enable the Interrupt component connected to interrupt */
    TC_CC_ISR_StartEx(Timer_INT_Handler);

7. Timer 인터럽트 함수를 정의합니다.
매 주기 마다 LED 1,2,3 을 토글합니다.

CY_ISR(Timer_INT_Handler)
{

    uint32 InterruptHpn;
    static uint8_t LED_1_stat=0,LED_2_stat=0,LED_3_stat=0;
    /* Check interrupt source and clear Inerrupt */
    InterruptHpn = Timer_1_GetInterruptSourceMasked();
    if (InterruptHpn == Timer_1_INTR_MASK_CC_MATCH)
    {
        Timer_1_ClearInterrupt(Timer_1_INTR_MASK_CC_MATCH);
    }
    else
    {
        LED_1_stat = 1-LED_1_stat;   // Toggle
        LED_2_stat = 1-LED_2_stat;   // Toggle
        LED_3_stat = 1-LED_3_stat;   // Toggle
        LED_1_Write(LED_1_stat);
        LED_2_Write(LED_2_stat);
        LED_3_Write(LED_3_stat);
        Timer_1_ClearInterrupt(Timer_1_INTR_MASK_TC);
    }
}

8. Main() 함수에서 Timer 를 시작하면, 다음처럼 주기적으로 LED 3개가 토글되어 깜박입니다.

main()
{
     :
    Timer_1_Start();
     :
}




9 이 프로그램의 압축된 파일은 다음 링크에 올려놓습니다.

2016년 1월 4일 월요일

[dialog] peripheral_examples (sys_tick + UART2 + GPIO_input + PWM)

BLE를 제외하고 Peripheral을 몇개 조합해서 프로그램을 테스트해 봤습니다.

16MHz 일반 CPU처럼 사용한 예죠.

제가 생각하기에는 BLE 칩인 DA14580을 BLE 통신으로만 사용하기엔 버리는 것이 많은데,
평소에 좀 다양하게 통신 외적인 것도 연습을 해 두는 것도 좋을 것 같았습니다.

필요할 때 찾아 프로그램을 하다 보면, 겨우 기능만 구현하고 코드도 엄청 지져분해 져서, 다시보면 머리속이 새하얘지도록 잊어버리는 경우가 많은 것 같습니다.


저는 아직까지, 프로젝트를 처음부터 새로 만드는 방법은 모르겠습니다. 그래서 systick 프로그램 원형에다 UART2,GPIO INPUT,PWM을 차례로 추가했습니다.

1. systick 예제는 원래 1초마다 GPIO를 인터럽트에 의해 Toggle 하는 프로그램인데, 50ms마다 인터럽트가 걸리고 50ms 인터럽트가 10번 걸릴때마다(500ms 마다) P1.1이 토클 되도록 프로그램했습니다.

2. UART2 로 GPIO INPUT으로 개발 키트의 스위치 2개의 입력을 받아서 입력 값을 터미날로 출력하도록 했습니다.

3. GPIO INPUT으로 받는 스위치 2개로 PWM을 변경하도록 했습니다.


여기서 하나, 좀 힘들었던 부분은 pwm.h 를 추가하는 방법을 몰라서 헤맸는데, 이것을 추가하는 방법은

1. Option for target 버튼을 누른 후,

2. C/C++ TAB 의 Include Path 버튼을 눌러 줍니다.

3. Folder Setup 메뉴의 New(Insert)를 눌러서 다음의 Path를 추가합니다.
..\..\..\..\..\..\sdk\platform\driver\pwm




이렇게 하니 PWM.h 파일이 왼쪽 main.c 밑에 나타나는군요. 그런 후에 컴파일하면 프로그램이 잘 돌아 갑니다.


예제 파일은 다음 링크에 압축해서 추가해 놓았습니다.

하드웨어 구성은 사진과 같습니다.



스위치를 누르면 PWM1,2가 대칭으로 누를 때마다 변경이 되어 출력됩니다.

PC의 터미날로 버튼을 누를때, 마다 키값과 현재 PWM 의 인덱스가 표시되도록 했습니다.

[dialog] 개발 키트에서 디지탈 기능 핀의 이동 테스트

다이얼로그 IC는 메뉴얼이 좀 부실한데,

핀의 기능을 몇가지를 제외하면 다양한 위치로 이동이 가능합니다.
ADC 는 P0.0~3 에서만 사용 가능, BLE_DIAG 기능은 P0.0~7 에서만 사용가능.
여기서 혹시 BLE_DIAG 가 뭔지 아시는 분 계신가요? 메뉴얼을 찾아 봤는데 모르겠군요.( 이놈에 메뉴얼~)

지난 번에 너무 과하게 이동시키는 바람에 부팅핀을 이동해서 보드를 다시 떴지만, ㅠㅠ


UART 핀을 여러 곳으로 이동을 해서 테스트를 해 봤습니다.

RXD 기능은 일단 제외했습니다. 터미날에서 입력을 사용하면 프로그램 복잡하여, TXD로 UART 잘 되는지만 봤습니다.

먼저 P0 에서의 핀을 바꿨습니다. 
P0.4 가 TxD 였던 것을 RXD로 바꾸고, P0.5 가 RXD 연던 것을 TXD로 바꿔서 TTL-to-232 장치를 거쳐 232-to-USB를 통해 PC의 터미널로 받아봤습니다.
여기서 사용한 프로젝트는 다음의 위치에 있습니다.
DA1458x_SDK_5.0.3\DA1458x_SDK\5.0.3\projects\target_apps\peripheral_examples\uart\Keil_5\uart.uvprojx

제가 사용하는 IC는 QFN40 이라 포트가 P0, P1, P2 이렇게밖에 없는데, 각 포트별로 2핀씩만 이동을 해 보겠습니다.


이 프로젝트의 user_periph_setup.h 파일의 다음 부분을 고쳤습니다.
#define UART2_GPIO_PORT    GPIO_PORT_0
#define UART2_TX_PIN       GPIO_PIN_7
#define UART2_RX_PIN       GPIO_PIN_4

개발 보드하고 포트 이동 위치 사진입니다.



[ 터미날 출력 ]

출력이 다 똑 같은데, 그냥 중복해서 올립니다. 누가 믿거나 말거나 각 포트마다 각각 출력 결과입니다. ^^


이번엔 P1.0 TXD 출력 테스트 입니다.
user_periph_setup.h 파일의 다음 부분을 고쳤습니다.
#define UART2_GPIO_PORT    GPIO_PORT_1
#define UART2_TX_PIN       GPIO_PIN_0
#define UART2_RX_PIN       GPIO_PIN_1

개발 보드하고 포트 이동 위치 사진입니다.

[ 터미날 출력 ]



이번엔 P2.0 TXD 출력 테스트 입니다.
user_periph_setup.h 파일의 다음 부분을 고쳤습니다.
#define UART2_GPIO_PORT    GPIO_PORT_2
#define UART2_TX_PIN       GPIO_PIN_0
#define UART2_RX_PIN       GPIO_PIN_1


개발 보드하고 포트 이동 위치 사진입니다.

[ 터미날 출력 ]