페이지

글목록

2016년 12월 15일 목요일

[CC1310/sub-1GHz] UART 흐름제어 설정

흐름제어 설정방법이 자세히 안 나와 있어서 직접 테스트를 해 봤습니다.

테스트를 진행한 프로젝트는 rfEasyLinkNp_cc1310 입니다.

설정방법은 간단합니다.


1. 만약 CTS,RTS 핀을 바꾸고 싶다면 CC1310_LAUNCHXL.h 파일에서 핀설정을 수정해 주시면 됩니다.
1
2
3
4
5
/* UART Board */
#define Board_UART_RX               IOID_2          /* RXD  */
#define Board_UART_TX               IOID_3          /* TXD  */
#define Board_UART_CTS              IOID_19         /* CTS  */
#define Board_UART_RTS              IOID_18         /* RTS */
cs



2. 그런 다음, CC1310_LAUNCHXL.c 의 BoardGpioInitTable[] 설정을
다음과 같이 수정하고..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const PIN_Config BoardGpioInitTable[] = {
    Board_RLED   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,         /* LED initially off             */
    Board_GLED   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,         /* LED initially off             */
    Board_BTN1   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,            /* Button is active low          */
    Board_BTN2   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,            /* Button is active low          */
    Board_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select    */
    Board_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                              /* UART RX via debugger back channel */
    Board_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                        /* UART TX via debugger back channel */
    Board_UART_CTS | PIN_INPUT_EN | PIN_PULLUP,
    Board_UART_RTS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
    //Board_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
    //Board_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
    //Board_SPI0_CLK | PIN_INPUT_EN | PIN_PULLDOWN,                                             /* SPI clock */
    PIN_TERMINATE
};
cs


3. CC1310_LAUNCHXL.c 의 uartCC26XXHWAttrs[CC1310_LAUNCHXL_UARTCOUNT] 의 내용 중,
.ctsPin 과 .rtsPin 설정을 수정합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* UART hardware parameter structure, also used to assign UART pins */
const UARTCC26XX_HWAttrsV1 uartCC26XXHWAttrs[CC1310_LAUNCHXL_UARTCOUNT] = {
    {
        .baseAddr       = UART0_BASE,
        .powerMngrId    = PowerCC26XX_PERIPH_UART0,
        .intNum         = INT_UART0_COMB,
        .intPriority    = ~0,
        .swiPriority    = 0,
        .txPin          = Board_UART_TX,
        .rxPin          = Board_UART_RX,
        .ctsPin         = Board_UART_CTS,    // PIN_UNASSIGNED -> Board_UART_CTS
        .rtsPin         = Board_UART_RTS    // PIN_UNASSIGNED -> Board_UART_RTS    
    }
};
cs


4. 빌드하고 다운로드하면 흐름제어 동작이 됩니다.

2016년 12월 14일 수요일

[STM32F4xx] Nucleo 보드 테스트 #24 (STLINK 테스트 : KEIL)


Necleo 보드에 달려있는 STLINK를 사용하는 방법을 알아보겠습니다.

저는 일단 STLINK 부분을 잘라버렸는데, 괜히 잘랐네요.
CN2 의 점퍼만 빼면 STLINK로 사용하고, 끼우면 NUCLEO 보드하고 같이 사용하도록 되어 있던것을 .. 에휴..

이 보드를 잘라 버리면 8MHz 클럭이 끊어지고 UART-to-USB 연결이 끊어져 버려서 Nucleo 보드를 못쓰게 되었습니다.
아깝네요.


잘라낸 쪽보드를 STLINK 로 사용하는 방법은 CN2의 점퍼를 모두 OPEN하고 
CN4 의 6핀 중, 5핀을 사용하면 됩니다.

그림 1장에 사용법이 다 나와있는데 다음과 같습니다.



다음은 실제로 잘라낸 STLINK 보드입니다.



다음은 회사에서 만든 Target 보드에 STLINK 핀을 뽑아 놓은 사진이고 , 위의 STLINK와 연결해서 다운로드 했는데 잘 동작됐습니다. 위에서 3.3V 라고 써 놓은 CN4의 1번핀은 VDD_TARGET 으로서 타겥보드에서 전원을 감지하는(DETECT) 역할을 한다.(전원을 공급하는 용도는 아님)


이정도 설명이면 다들 알아 들으시겠죠? ^^

[STM32F4xx] Custom 보드 테스트 #23 (USB CDC.STM32F446 : KEIL)

이번에는 STM32F446에서 USB CDC(Communication Device Class) = USB Virtual Comport Serial Driver 기능을 테스트해 보겠습니다. 


회사에서 제작한 보드에는 WLCSP 타입의 STM32F446 IC를 사용해서 CUBEMX 툴에서 패키지를 바꿨습니다.


[회사에서 제작한 보드]




아이고 그런데, 설계를 USB HS 포트에 연결을 해놨네.. @@
이번에 처음 테스트를 했는데, 결과적으로 USB DFU 와 CDC 모두 잘 됐습니다.

USB CDC 는 정말 간단합니다. CUBEMX 툴에서 설정만 제대로 하면 거의 다 된 것입니다.
하지만 아무리 해도 CDC가 UART 포트로 잘 안잡혔는데, 유튜브 동영상 보고 수정하니까 잘 됩니다.
이 내용은 나중에 말씀드리겠습니다.

먼저 CUBEMX 툴로 PINOUT 설정에서 필요한 기능들을 정의합니다.

1. USB_HS 포트에 internal FS Phy 를 Device Only 로 설정.




2. RCC 에서 HSE 를 Crystal 로 설정. MiddleWares 의 USB_DEVICE 에 CDC로 설정.




3. 클럭 설정에서 외부 클락을 24MHz로 수정하고 HCLK 를 180MHz로 수정하고 엔터치면 오랜 시간이 걸린 후에 168MHz로 자동으로 계산해 주는데, 자주 하다 보니 그냥 처음부터 168MHz를 써 주면 금방 설정이 완료 됩니다.




4. 마무리로 프로젝트 이름 넣어주고 Toolchain / IDE를 Keil로 설정하고 Generate code 를 클릭하면 Keil 코드가 만들어 집니다.




5. 그냥 이대로 KEIL 에서 컴파일해서 다운로드해 주면 다음과 같이 PC 장치관리자에서 USB CDC 는 보이는데,
오류가 발생합니다.

다음의 Youtube 영상의 2:36 부분부터 유심히 보시면 저와 같은 결과에 어떻게 대응하는지 잘 나와 있습니다.저도 이 영상보고 수정해서 성공했습니다.









6. 수정할 코드는 usbd_cdc.h 의 CDC_DATA_HS_MAX_PACKET_SIZE 의 값이 잘 못 되어 있습니다. (^^ 저는 원리도 모르겠고 그냥 따라했는데 잘 되요.)
아뭏든 512 를 256 으로 고치면 정상적으로 PC에서 COM PORT가 잡힙니다.




7. PC장치관리자에서 포트 확인


8. 이렇게까지 하면 포트만 생성됐지 터미날 연결하면 아무짓도 안하는게 당연하겠죠? ^^
USB UART 출력 함수는 usbd_cdc_if.c 파일 안에 uint8_t CDC_Transmit_HS(uint8_t* Buf, uint16_t Len) 함수를 사용하면 됩니다.

간단한 예로,
CDC_Transmit_HS("Try..!!\n\r",9); 하면 
터미날에 ..
Try..!!

라고 출력 됩니다.

그런데 printf 함수가 참 편하므로 이것도 printf() 함수 쓰는 방법을 알아보겠습니다.
예전에 UART에서 사용하던 것과 같이 tx 함수만 CDC_Transmit_HS() 함수로 수정해 주면 됩니다.

main.c 파일에 다음과 같이 추가해 주시면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
/* USER CODE BEGIN 0 */
#ifdef __GNUC__
 #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
 #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
 while(CDC_Transmit_HS((uint8_t *)&ch, 1== USBD_BUSY);
 return ch;
}
cs

그런 다음에 필요한 곳에서 printf() 함수를 사용하시면 됩니다.
끝...

이런 한가지 빼 먹었습니다. #include 에 다음과 같이 추가해 주세요.
1
2
3
4
5
6
7
8
9
10
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "usb_device.h"
 
/* USER CODE BEGIN Includes */
#include "string.h"
#include "usbd_cdc_if.h"
/* USER CODE END Includes */
cs

이것은 따로 프로젝트 파일 첨부하지 않겠습니다.
너무 간단하니까요. ^^

[da1458x] 최신 SDK 내용은 다루지 않겠습니다.

da14583 최신 SDK로 dsps를 정리해 보려 했다가,

그냥 예전 버전의 dsps 프로그램을 사용하기로 했습니다.

이유는 제가 BLE를 처음 시작한 칩이 dialog 칩이었는데, 
특별히 좋은 점이 없었습니다.

작은 칩이여서 썼는데, otp 타입이고 외부 Flash를 추가하면 전체적으로 더 큽니다.
플레쉬 타입(da14583)은 5x5mm 로 노르딕 wlcsp 타입보다 큽니다.
또 보드어드레스도 따로 구입해서 집어 넣어야 하는데, 노르딕은 들어 있습니다.
아마도 다른 칩들은 다 들어 있는듯 합니다.

싸이프레스 psoc4도 괜찮은데, BLE-to-UART 정식 Profile이 없고 Custom Profile만 있으니,
부족한 부분이 좀 있는 것 같고...

계속해서 BLE를 사용한다면 그냥 노르딕 nrf51822 을 쓸 예정인데,
그것도 esp32 칩으로 BLE 를 뚫으면 안 쓸 예정입니다.

아마도 ESP32 가 Wireless 칩으로는 가성비가 갑인듯 합니다.
BLE 값에 Wifi도 같이 되고, 듀얼코어라서 CPU로도 사용할 수 있으니 말입니다.
단점은 제가 리눅스를 잘 몰라서 개발환경을 아직도 구축을 못하고 있네요.

얼른 환경 구축해서 사용해 봐야겠네요.

[PSOC5] SD Card I/F (SPI 방식)

안녕하세요, 

이 글은 예정에는 없었지만, 카페에 올린줄 알았는데 없어서 글을 쓰게 되었습니다.

PSOC5에서 micro SD-Card 를 사용하는 방법인데, PSOC5은 SDIO 가 없어서 SPI 방식만 지원합니다.
속도는 24Mhz 입니다.
제가 보기에는 현재까지 PSOC5가 MCU 중에서 가장 사용자 친화적으로 잘 만들어 진 것 같은데,
패키지가 다양하지 않고 후속 모델(PSOC6)이 안나오며, PSOC4만 계속 손데고 있어서 매우 불만이 많습니다.
가격은 요새 좀 내려간 듯 한데, STM32F4xx 에는 가성비가 못미치네요.
PSOC5 이대로 죽는겐가? ㅜㅜ

아.. 헛소리를 많이 했군요. 
그럼 다시 PSOC5에서 SPI 방식으로 SD Card 제어하는 방법을 알아보겠습니다.
PSOC Creator 의 TopDesign.cysch 에 emFile SPI Mode[V1.20] 콤포넌트를 배치하고 
emfile 콤포넌트의 Datasheet를 보면 여기서 설명하려는 내용이 영문으로 나와 있습니다.


1. PSOC Creator 내부에 File System 라이브러리가 없기 때문에 먼전 File System 라이브러리를 다운로드 받아야 합니다.
여기(링크)에서 다운로드 받으시면 됩니다.

2. 받은 파일을 압축을 풀어서 적당한 위치에 놓으십시요. (저는 프로젝트 폴더 옆에 놓았습니다)

3. 콤포넌트 창에서 Communication->FileSystem->emFile 을 TopDesign.cysch 으로 끌고 와서 배치합니다.



4. 왼쪽 Workspace Explorer 의 Project 를 우클릭하여 Build Setting 을 클릭합니다.



5. Include Directory 를 추가




6. 라이브러리 이름 추가. 직접 타이핑해 줍니다.
emf32noslfn 를 타이핑 하고, 이 의미는 No OS , Long File Name 의 의미입니다.



7. 다음은 라이브러리가 있는 디렉토리를 추가합니다.



8. 라이브러리 파일을 추가합니다.



9. 회로를 보고 핀을 배치합니다. (PSOC5는 이것이 장점 : 핀을 맘대로 옮길 수 있습니다.)
디버깅용으로 USB Serial 포트도 하나 넣었습니다.




10. micro-SD 카드 회로도는 다음과 같습니다. 신호에 굳이 풀업저항은 필요 없었습니다.
혹시나 해서 테스트 해 봤는데 잘 되네요.



11. SD 카트에서 데이터를 읽어서 뿌려볼라고 하는데, 구글링해서 "영문 텍스트 소설" 검색하니 해리포터 불의잔이 있네요. ^^
다운받아서 SD Card에 넣습니다.




12. 제작한 기판에 SD Card를 끼웁니다. 회사에서 만든 기판은 다음과 같습니다.




이제 프로그램만 짜면 되는데 불의잔을 읽어서 USB Serial로 터미날에 5000 바이트만 뿌려 보겠습니다.
먼저 결과를 올려 보겠습니다.



잘 읽히네요. 불의 잔. ^^

소스코드는 main.c 에만 코드를 추가했고, SD Card 읽기만 테스트 해 봤습니다.
나머지는 현재까지 읽기 이외의 작업이 필요없었던 관계로 회원 여러분이 찾아서 해 보십시요. ^^
프로젝트 압축해서 첨부합니다. 그런데 emfile 라이브러리는 PSOC Creator에서 한번에 압축을 안해 주네요.
아마도 4~8 과정을 회원분들께서 다시 해 주셔야 될 것 같습니다.

프로젝트 파일 (링크)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "project.h"
#include <stdio.h>
#include <FS.h>
#define BUFFER_LEN  64u
struct tagFILE
{
    uint8 accmd;
    uint32 sz;
    FS_FILE* fp;
    char tFileName[64];
};
static struct tagFILE   tFILE;
char8 *parity[] = { "None""Odd""Even""Mark""Space" };
char8 *stop[] = { "1""1.5""2" };
void ready_USB_UART_tx(void);
int main(void)
{
    uint8_t buffer[5000];
    uint16_t i;
    char usb_tx[BUFFER_LEN];
    
    
    FS_Init();
    FS_Mount(0);
    FS_FAT_SupportLFN();
    
    CyGlobalIntEnable; /* Enable global interrupts. */
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    
    CyDelay(500);
    
    FS_DIR*     pDir;
    USBUART_1_Start(0u, USBUART_1_3V_OPERATION);
    ready_USB_UART_tx();
    pDir = FS_OpenDir("");
    sprintf(tFILE.tFileName,"Harry_potter_Goblet_of_Fire.txt");
    tFILE.fp = FS_FOpen(tFILE.tFileName, "rb");
    tFILE.sz = FS_GetFileSize (tFILE.fp);
    sprintf(usb_tx,"File size : %5lu\n\r",tFILE.sz);
    while(USBUART_1_CDCIsReady() == 0u);    /* Wait till component is ready to send more data to the PC */ 
    USBUART_1_PutString(usb_tx);       /* Send data back to PC */
    
    FS_FSeek(tFILE.fp,0,0);
    FS_Read(tFILE.fp, buffer, 5000);
    for (i=0;i<5000;i++)
    {
        while(USBUART_1_CDCIsReady() == 0u);    /* Wait till component is ready to send more data to the PC */ 
        USBUART_1_PutChar(buffer[i]);       /* Send data back to PC */
    }
    //proc_USB_UART();
    for(;;)
    {
        /* Place your application code here. */
    }
}
void ready_USB_UART_tx(void)
{
    uint16 count;
    uint8 state,led_st=0,cnt_USB_UART_con=0;;
    uint8 buffer[BUFFER_LEN];
    char tx_buffer[BUFFER_LEN];
   /* Main Loop: */
    for(;;)
    {
        if(USBUART_1_IsConfigurationChanged() != 0u) /* Host could send double SET_INTERFACE request */
        {
            if(USBUART_1_GetConfiguration() != 0u)   /* Init IN endpoints when device configured */
            {
               /* Enumeration is done, enable OUT endpoint for receive data from Host */
                USBUART_1_CDC_Init();
            }
        }         
        if(USBUART_1_GetConfiguration() != 0u)    /* Service USB CDC when device configured */
        {
            if(USBUART_1_DataIsReady() != 0u)               /* Check for input data from PC */
            {   
                count = USBUART_1_GetAll(buffer);           /* Read received data and re-enable OUT endpoint */
                if(count != 0u)
                {
                    while(USBUART_1_CDCIsReady() == 0u);    /* Wait till component is ready to send more data to the PC */ 
                    USBUART_1_PutData(buffer, count);       /* Send data back to PC */
                    /* If the last sent packet is exactly maximum packet size, 
                    *  it shall be followed by a zero-length packet to assure the
                    *  end of segment is properly identified by the terminal.
                    */
                    if(count == BUFFER_LEN)
                    {
                        while(USBUART_1_CDCIsReady() == 0u); /* Wait till component is ready to send more data to the PC */ 
                        USBUART_1_PutData(NULL, 0u);         /* Send zero-length packet to PC */
                    }
                }
            }  
            
            state = USBUART_1_IsLineChanged();              /* Check for Line settings changed */
            if(state != 0u)
            {  
                if(state & USBUART_1_LINE_CODING_CHANGED)   /* Show new settings */
                {
                    sprintf(tx_buffer,"BR:%4ld,DB:%d\n\r",USBUART_1_GetDTERate(),(uint16)USBUART_1_GetDataBits());
                    sprintf(tx_buffer,"SB:%s,Parity:%s\n\r", stop[(uint16)USBUART_1_GetCharFormat()], \
                                                         parity[(uint16)USBUART_1_GetParityType()]);
                }
                if(state & USBUART_1_LINE_CONTROL_CHANGED)  /* Show new settings */
                {   
                    state = USBUART_1_GetLineControl();
                    sprintf(tx_buffer,"DTR:%s,RTS:%s\n\r",  (state & USBUART_1_LINE_CONTROL_DTR) ? "ON" : "OFF", \
                                                        (state & USBUART_1_LINE_CONTROL_RTS) ? "ON" : "OFF");
                    cnt_USB_UART_con++;
                    
                    if (cnt_USB_UART_con > 1)
                        break;
                }
            }
        }
    }   
}
cs