일단 Cube Mx 또는 예전의 Std 라이브러리 등을 이용하여 VCP를 활성화 합니다.

 

USB선택후 Device 선택한뒤 (우측의 USB_DP / USB_DM 이 자동 선택됨)

USB_DEVICE 에서 Communication Device 를 선택합ㄴ디ㅏ. (그럼 VCP 기능이 사용 가능)

 


본인은 IDE 툴은 uVision 을 사용하므로 프로젝트 옵션에서 
printf 를 제공하는 MicroLib를 체크 합니다.

사용자 삽입 이미지

 

일반적으로 Main.c 에 하기 내용을 추가 합니다.

 


struct __FILE{int handle;};

FILE __stdout;

int fputc(int c, FILE *f);



 

VCP 라이브러리에서 CDC_Transmit_HS 함수 또는 FS로 되어있는 함수가 생성되면

main 함수에 Extern 선언하여 하기와 같이 사용 하면 됩니다.

 


int fputc(int c, FILE *f)

{

uint8_t temp;



temp= (uint8_t)c;

CDC_Transmit_HS(&temp,1); // 실제 출력 함수 설정.

return c;

}

 

 

이후에

printf 함수를 사용하면 정상적으로 출력 됨을 확인 가능.

 

 

추가사항.

간혹 VCP 관련 하여 장치관리장에서 정상적으로 인식 되지 않는 이슈가 있으며 (어떤PC마다 될때 있고 안될때가 있음)

해당 사항 발생시 startup_stm32fxxx.S 로 시작되는 파일을 열면 어셈으로 되있는 부분에서

Stack_Size        EQU     0x800

Heap_Size      EQU     0x800

 

스택 및 힙사이즈를 늘려서 재컴파일 해봐야함.

#printf, #디버깅, #cortex-M3, #cortex-M4, #VCP

크리에이티브 커먼즈 라이센스
Creative Commons License
2017/08/02 00:13 2017/08/02 00:13

댓글을 달아 주세요

이번에 산업용 PC 설계 프로젝트를 진행하면서

NTC 온도 센서를 이용하여 보드의 온도 상태를 확인 하기 위해

기존에 학습했던 온도 센서 (http://ippuu.iptime.org/53) 자료를 이용하여 API 형태로 구현 하였다.
 


typedef unsigned char  u08;
typedef unsigned short u16;
//NTC 관련 구조체 선언.
typedef struct
{
	float ADC_PW_V; // ADC에 사용되는 레퍼런스 기준 전압 이다. ex) ADC_PW_V = 3.3;
	u16 NTC_Res; // NTC 저항의 실제 수치를 넣으면 된다 .ex) 1K옴 저항의 경우  NTC_Res = 1000; 
	u16 NTC_Beta; // NTC 저항의 제조사에서 제공되는 β Value 를 입력한다.
	u16 R1_Res; // NTC 저항을 측정하기 위한 기준 분압 저항을값을 입력한다.
	u16 ADC_Scale_Level; // ADC의 해상도를 입력한다  ex) ADC_Scale_Level = 1024; //10bit ADC
	u16 ADC_Read_Value; //ADC에서 NTC 저항의 읽어들인 값을 넣는다.
}st_NTC_CAL;


//함수원형
float Temperature_calculrator(st_NTC_CAL* pNTC)
{
	double r;
	double ADC_STEP_VOLTAGE;
	float Temperature;

	 ADC_STEP_VOLTAGE = pNTC->ADC_PW_V/ pNTC->ADC_Scale_Level;


	r = pNTC->R1_Res/((pNTC->ADC_PW_V/(pNTC->ADC_Read_Value*ADC_STEP_VOLTAGE))-1.0);
	Temperature = 1.0/(log(r/pNTC->NTC_Res)/pNTC->NTC_Beta+(1.0/(25.0+273.0))) - 273;

	return Temperature;

}



실제 구현 방법은 하기와 같다.


void anthing_func()
{
	st_NTC_CAL st_NTC;
	unsigned int PW;
	float PWTEMP;


	//NTC Calcurator Struct init
	st_NTC.ADC_PW_V = 3.4; // 3.4V
	st_NTC.ADC_Scale_Level = 1024; // 10bit
	st_NTC.NTC_Beta = NTC_BETA; //3706
	st_NTC.NTC_Res = NTC_RESISTOR; // 1000 1Kohm
	st_NTC.R1_Res = R1_OHM; // 3300ohm

	PW = ADC_Read();

	st_NTC.ADC_Read_Value = PW; // ADC를 통해 읽어들인 값을 구조체에 집어 넣는다.
	PWTEMP = Temperature_calculrator(&st_NTC);
	printf("PW TEMP2 : [%.2f]\r\n",PWTEMP); // 출력하여 확인한다.

      }


크리에이티브 커먼즈 라이센스
Creative Commons License
2017/02/03 23:57 2017/02/03 23:57

댓글을 달아 주세요

 

우선 u8glib는 GLCD 기반의 그래픽 라이브러리 입니다.

arduino에서 많이 사용되고 있는것으로 보이며,

c언어 기반이라 포팅 가능할것으로 보여 구글링 도움을 받아 진행 하였습니다.
사실 진행 작업은 크게 어렵지 않습니다.
1. H/W Device initialize
2. g8lib H/W HAL(Hardware Access Layer) 연동
3. Draw 해서 사용하기만 하면 끝
먼저 H/W제어 device 초기화 관련 부부은

STmicro 에서 제공되는 CubeMX 툴을 이용하여 GPIO 및 SPI 인터페이스의 초기 화를 진행 하였습니다.
Cube MX 에서 컴파일러는 Keil로 설정 하였습니다.[

]
CubeMX 설정 파일을 다운로드 하여 사용하시기 바랍니다.
CubeMX의 장점은
어지간한 H/W initialize는 선택한 컴파일러의 프로젝트 파일과 소스코드가 생성되므로
사용자는 main문 내부에서 바로 구현가능하다는 점에 있습니다.

 

2. HAL 연동
이후 사용자는 u8g_arm.c 과 u8g_arm.h 파일을 생성합니다.
u8g_arm.c


#include "u8g_arm.h"  

void u8g_Delay(uint16_t val)  

{  

      HAL_Delay(val);  

}  

void u8g_MicroDelay(void)  

{  

      HAL_Delay(1);  

}  

void u8g_10MicroDelay(void)  

{  

      HAL_Delay(1);  

}  

uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)  

{  

  switch(msg)  

  {  

   case U8G_COM_MSG_STOP:  

    break;  

   case U8G_COM_MSG_INIT:  

    u8g_MicroDelay();  

    break;  

   case U8G_COM_MSG_ADDRESS:           /* define cmd (arg_val = 0) or data mode (arg_val = 1) */  

    u8g_10MicroDelay();  

    HAL_GPIO_WritePin(PORTB, DC, (GPIO_PinState)arg_val);  

    u8g_10MicroDelay();  

    break;  

   case U8G_COM_MSG_CHIP_SELECT:  

    if ( arg_val == 0 )  

    {  

         HAL_Delay(1);  

         HAL_GPIO_WritePin(PORTA, CS, GPIO_PIN_SET);  

    }  

    else  

      HAL_GPIO_WritePin(PORTA, CS, GPIO_PIN_RESET);  

    u8g_MicroDelay();  

    break;  

   case U8G_COM_MSG_RESET:  

    break;  

   case U8G_COM_MSG_WRITE_BYTE:  

     HAL_SPI_Transmit(&SPI_HANDLER, &arg_val, 1, 10000);  

     while(HAL_SPI_GetState(&SPI_HANDLER) != HAL_SPI_STATE_READY);  

     u8g_MicroDelay();  

     break;  

   case U8G_COM_MSG_WRITE_SEQ:  

   case U8G_COM_MSG_WRITE_SEQ_P:  

    {  

         HAL_SPI_Transmit(&SPI_HANDLER, (uint8_t *)arg_ptr, arg_val, 10000);  

         while(HAL_SPI_GetState(&SPI_HANDLER) != HAL_SPI_STATE_READY);  

         u8g_MicroDelay();  

         arg_val = 0;  

    }  

    break;  

  }  

  return 1;  

}  


 

u8g_arm.h

 



#ifndef _U8G_ARM_H  

#define _U8G_ARM_H  

#include "u8g.h"  

#include "stm32f1xx_hal.h"  

#define SPI_HANDLER hspi2 // use your SPI hadler  

extern SPI_HandleTypeDef SPI_HANDLER;  

#define DC GPIO_PIN_12  

#define CS GPIO_PIN_8

#define PORTB GPIOB

#define PORTA GPIOA

uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);  

#endif





추가적으로 main 문에 하기와 같이 추가 해주면 끝입니다..
로고는 LCDAssistant를 이용하여 C 파일로 변환후 출력 하였습니다.




//main.c
u8g_t u8g;
u8g_InitComFn(&u8g, &u8g_dev_ssd1306_128x64_hw_spi, u8g_com_hw_spi_fn);

while(1)
{
u8g_FirstPage(&u8g);  
	 do  
	 {	

		  
		  u8g_DrawBox(&u8g,0,0,127,10);
		  
		  u8g_DrawBitmapP(&u8g,0,10,13,19,(const uint8_t *)&img);

		  u8g_DrawFrame(&u8g,0,29,127,15);	

		  u8g.font = u8g_font_courR08;//u8g_font_profont22;  
		  u8g_DrawStr(&u8g, 10, 40, "Research Engeneer");

		  u8g.font = u8g_font_7x13B;//u8g_font_profont22;  
		  u8g_DrawStr(&u8g, 10, 56, "S.Jung");
	
	
		
	 } while ( u8g_NextPage(&u8g) );  
    /* refresh screen after some delay */
    u8g_Delay(100); 
}
사용자 삽입 이미지

Bar 그리기 및 삭각테두리, 이미지, 텍스쳐 등등
 
잘 동작 됩니다. 단지 폰트가 많아서 안쓰는 것들은 좀 제거를 해야할듯 보입니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2017/01/16 23:10 2017/01/16 23:10

댓글을 달아 주세요

  1. 스스 2017/02/23 13:38  address  modify / delete  reply

    안녕하세요?
    말씀하신대로 해보니 아래와같은 에러가 나오는데 원인을 알수있을까요?

    linking...
    Oled\Oled.axf: Error: L6218E: Undefined symbol u8g_InitComFn (referred from main.o).
    Oled\Oled.axf: Error: L6218E: Undefined symbol u8g_dev_ssd1306_128x64_hw_spi (referred from main.o).

    감사합니다.

    • 홈키파 2017/02/23 18:48  address  modify / delete

      컴파일러 개발툴의

      프로젝트에서

      해당 파일을 추가 하고

      컴파일 진행 하셨는지요???

      혹시 하기의 헤더 파일이 인클루드 되어 있지 않다면

      소스에 추가 하시기 바랍니다.

      #include "u8g.h"

커널 파일 경로에서 Drivers 폴더 경로로 이동하면 
#>Kernel file/drivers
설계된 Device Driver파일을 원하는 폴더의 위치로 이동시킨다.

파일을 복사하고

obj-$(CONFIG_HELLO_MODULE)  +=hello.o

다시 cd ..을 이용하여 상위 폴더 (#>Kernel/Drivers)로 이동하여

Makefile을 수정한다. 여기서는 디렉토리 명을 명기한다.

 

크리에이티브 커먼즈 라이센스
Creative Commons License
2015/03/29 21:32 2015/03/29 21:32

댓글을 달아 주세요

1KD-5K NTC 센서를 이용하여
온도를 그래프로 표현한다.
시간이 지남에 따라 X축 방향으로 온도의 변화량이 표시된다.

그래프는 노가다로 좌표찍어가면서

GUI 구현 ㅎㄷㄷㄷㄷ

사용자 삽입 이미지

일단은 라이터로 가열하여 정상 적으로 나타나는지 검증 진행 ㅋ

Reflow Oven D.I.Y 에 적용 예정
크리에이티브 커먼즈 라이센스
Creative Commons License
2014/11/26 01:41 2014/11/26 01:41
Tag // , ,

댓글을 달아 주세요

먼저 온도 측정을 위한 NTC 저항 관련 계산 방법은 하기 참고 문서를 참조한다.

NTC에서 온도에 따른 저항값의 변화는 리니어하지 않으므로 NTC 판매 업체의

β정수를 이용하여 계산하여야 한다.

하기 코드의 200~201번 라인을 참조하여 계산하면 된다.


/**   ******************************************************************************   * @file    main.c   * @author  MCD Application Team   * @version V1.0.0   * @date    18-April-2011   * @brief   Main program body   ******************************************************************************   * @attention   *   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.   *   * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>   ******************************************************************************     */ /* Includes ------------------------------------------------------------------*/ #include "stm32f2xx.h" #include "usart.h" #include "JOYState.h" #include "LCD/LCD.h" #include <math.h> #define ADC3_DR_ADDRESS    ((uint32_t)0x4001224C) #define AVCC_mv 3300.0 #define NTC_Resistor 1000 //1Kohm __IO uint16_t ADC3ConvertedValue = 0; __IO uint32_t ADC3ConvertedVoltage = 0; void  Delay (uint32_t nCount) {   for(; nCount != 0; nCount--); } void ADC3_CH7_DMA_Config(void); void Display(void); /**   * @brief  Main program   * @param  None   * @retval None   */ GPIO_InitTypeDef t_Gpio_init; int main(void) {   /*!< At this stage the microcontroller clock setting is already configured,        this is done through SystemInit() function which is called from startup        file (startup_stm32f2xx.s) before to branch to application main.        To reconfigure the default setting of SystemInit() function, refer to         system_stm32f2xx.c file      */     SystemInit();   SystemCoreClockUpdate(); USART_Configuration(); USART_NVIC_Config(); //JOYState_LED_GPIO_Init(); LCD_Initializtion(); ADC3_CH7_DMA_Config(); ADC_SoftwareStartConv(ADC3); LCD_Clear(Red); GUI_Text(132,104,"Open207Z",White,Red); //GUI_Text(76,120,"Development Board V1.0",0xFFEF,Red); Delay(0xffffff); LCD_Clear(Red); GUI_Text(76,120,"Development Board V1.0",White,Red); Delay(0xffffff); LCD_Clear(Red); printf("\r\nBoot Success\r\n"); while (1) { ADC3ConvertedVoltage = ADC3ConvertedValue *3300/0xFFF; Display(); Led_Toggle(Read_JOYState()); } } void ADC3_CH7_DMA_Config() { ADC_InitTypeDef  ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef  DMA_InitStructure; GPIO_InitTypeDef  GPIO_InitStructure;   /* Enable ADC3, DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOF, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); /* DMA2 Stream0 channel2 configuration **************************************/ DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); /* Configure ADC3 Channel7 pin as analog input ******************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOF, &GPIO_InitStructure); /* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); /* ADC3 Init ****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC3, &ADC_InitStructure); /* ADC3 regular channel7 configuration *************************************/ ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 1, ADC_SampleTime_3Cycles); /* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); /* Enable ADC3 DMA */ ADC_DMACmd(ADC3, ENABLE); /* Enable ADC3 */ ADC_Cmd(ADC3, ENABLE); } void Display(void) {     /*       resistance value of NTC:       r(25)=500 Ohm       r(t)=r(25)*e^(3300*(1/(t+273)-1/(25+273)))       etc,       r(-20)=3.58 KOhm       r(-3)=1576 KOhm       r(60)=156 Ohm       r(100)=54 Ohm       ...       if R1=5.6KOhm, then:       V_in(t)=AVCC*(r(t)/(r(t)+R1))       etc,       V_in(-3)=1098 mv       V_in(100)=47.7 mv       ...             when V_in is known,       r=R1/((AVCC/V_in)-1)       because of B=3300K, r(25)=500 Ohm:       t=(1/((ln(r/500)/3300)+(1/(25+273))))-273     */ unsigned long v=0,mv=0,temp1=0,temp2=0,temp=0; float r,t; unsigned char i=0,temp_buf[3]; v=(ADC3ConvertedVoltage)/1000; mv = (ADC3ConvertedVoltage%1000)/100; temp1 = (3300 - ADC3ConvertedVoltage);  //1K Resister ADC Value temp2 = temp1 / 100; // Amp temp = (ADC3ConvertedVoltage*10) / temp2; //NTC Resister Value printf("1K Resister Voltage:%d\r\n",temp1); printf("1K Resister AMP    :%d\r\n",temp2); printf("NTC Resister Value :%d\r\n",temp); printf("Voltage = %d,%d V   \r\n",v,mv); printf("ADC = %d   \r\n",ADC3ConvertedValue); r= NTC_Resistor /((AVCC_mv/ADC3ConvertedVoltage)-1.0); t=1.0/(log(r/1000)/3950+(1.0/(25.0+273.0))) - 273; printf("Temperature = %3f   \r\n",t); i = (unsigned char)t; temp_buf[0] = (t/10)+48; temp_buf[1] = ((char)t%10)+48; GUI_Text(50,137,"ADC Temperature Senising",White,Red); GUI_Text(76,120,&temp_buf[0],White,Red); GUI_Text(92,120,"C",White,Red); Delay(0xffffff); } #ifdef  USE_FULL_ASSERT /**   * @brief  Reports the name of the source file and the source line number   *         where the assert_param error has occurred.   * @param  file: pointer to the source file name   * @param  line: assert_param error line source number   * @retval None   */ void assert_failed(uint8_t* file, uint32_t line) {   /* User can add his own implementation to report the file name and line number,      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */   /* Infinite loop */   while (1)   {   } } #endif /**   * @}   */ /**   * @}   */ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
크리에이티브 커먼즈 라이센스
Creative Commons License
2014/11/23 20:10 2014/11/23 20:10

댓글을 달아 주세요

  1. Livali Ageless Moisturizer Review 2018/06/23 09:41  address  modify / delete  reply

    I hardly drop comments, but i did a few searching and wound up here S.Jung
    :: [Cortex-M3] DMA를 이용한 ADC 측정으로 NTC
    저항값 잀어들이기. And I actually do have a
    few questions for you if you usually do not mind.
    Is it simply me or does it look like a few of these remarks come across like they are written by brain dead individuals?
    :-P And, if you are posting on additional places, I would
    like to keep up with everything fresh you have to post.
    Would you list of every one of your public pages like your Facebook page,
    twitter feed, or linkedin profile?

  2. Livali Skin Care 2018/07/03 11:06  address  modify / delete  reply

    I almost never comment, but i did a few searching and wound up here S.Jung :: [Cortex-M3] DMA를 이용한 ADC 측정으로 NTC 저항값 잀어들이기.
    And I do have a couple of questions for you if it's allright.

    Could it be only me or does it look like some of the
    comments come across like written by brain dead individuals?
    :-P And, if you are posting on additional places, I'd like to follow anything fresh you have to post.
    Would you make a list of every one of all your shared
    sites like your Facebook page, twitter feed, or linkedin profile?

  3. Ultra Shave Forskolin 2019/03/13 09:42  address  modify / delete  reply

    I hardly comment, however i did some searching and wound up here S.Jung :
    : [Cortex-M3] DMA를 이용한 ADC 측정으로 NTC 저항값 잀어들이기.
    And I do have a couple of questions for you if you tend not to mind.

    Is it just me or does it look like some of the responses come across like coming from brain dead visitors?
    :-P And, if you are posting on additional online social sites, I'd like to follow anything
    fresh you have to post. Could you make a list of every one of your shared pages like your Facebook page, twitter feed, or linkedin profile?

[Cortex-M3]uC/GUI 관련

from Firmware 2014/05/07 00:25

현재 보유하고있는 개발 보드의 예제에서는 uC/OS-II를 이용하여 uC/GUI 를 사용하는 방식을 취하고 있었다.

3개의 Task를 생성 해서 터치 관련 Task, GUI 관련 Task,  LED Blink Task등 총 3개의 Task를 구동하는 방식이었다.

일단 SPI 메모리 복사에 사용할 GUI 터치 화면을 구성하기 위하여 GUI 라이브러리 개발 보다 범용 TFT GUI 라이브러리를

사용하기로 결정하고 굳이 RTOS를 사용할 필요성이 없어 Non-OS용으로 수정 적용 하였다

일단 환경설정 관련 Config파일에서 OS 사용 하지 않도록 설정 하였으며  GUI_Init 함수등을 수정 하였다.




장점은 GUI 라이브러리가 구성되어있어 TFT화면 구성이 용이하며(노가다를 하지 않아도 된다.)

BMP 파일 변환후 쉽게 띄울수 있어 회사 로고도 띄워보고

Text 폰트의 변환 또는 구성등이 용이하다

일단 화면 띄우는데 까지만 하고 추후 터치 관련 인식함수 적용 예정후 SPI Flash 복사용 GUI 화면 구성 예정이다


현재 까지 진행된 코드느 하기 압축파일에 첨부함. 끗.

크리에이티브 커먼즈 라이센스
Creative Commons License
2014/05/07 00:25 2014/05/07 00:25

댓글을 달아 주세요

  1. 비밀방문자 2015/03/23 22:46  address  modify / delete  reply

    관리자만 볼 수 있는 댓글입니다.

  2. 비밀방문자 2018/05/07 09:12  address  modify / delete  reply

    관리자만 볼 수 있는 댓글입니다.

    • 홈키파 2018/05/09 09:08  address  modify / delete

      www.waveshare.com 홈페이지에 들어가시면

      예제 코드등 받으실수 있습니다.

      비번은 저도 잊어버려서 안열리네요 ㄷㄷ

[Cortex-M3]SPI 통신 관련

from Firmware 2014/01/06 22:48

STM32F207Z 모델에서 SPI1 과 SPI2 를 사용하려고 하였다

사용 요점은

SPI2의 Flash Memory에서 SPI1 Flash Memory로 복사를를 수행한다.

문제는 SPI1에서 Interface가 정상적으로 이루어 지지 않는다.

자꾸 값이 이상해서 결국에 디버거로 추적해보니까

SPI_I2SPR 레지스터는 건드리지도 않았는데 Default Reset Value : 0x00000002 로 초기화 되어야함에도 불구하고

SPI1의  SPI_I2SPR 레지스터는 Value 값이 0x00000000 으로 초기화 된다. ㅎㄷㄷㄷ.

 

20140105_225209

 

뭐 그리고 Interface 도 안되고. Datasheet 찿아봐도 Forbidden Value 라고 명기되어있고 SPI 모드에서는

상관없다고 되어있는데 …..

돌아벌겄고만… 뭐 어쩌라고? ㅎㄷㄷㄷㄷ

크리에이티브 커먼즈 라이센스
Creative Commons License
2014/01/06 22:48 2014/01/06 22:48

댓글을 달아 주세요

[CORTEX-M3]TFT-LCD 구동

from Firmware 2013/10/16 22:58

DSCF111331

 

Cortex-M3

UART 및 TFT-LCD 구동 연습중.펀치

크리에이티브 커먼즈 라이센스
Creative Commons License
2013/10/16 22:58 2013/10/16 22:58

댓글을 달아 주세요

RCC Setting -STM32F2XX Series 데이터 시트를 보다가 머리속에 맴돌아 정리하여 올림.
크리에이티브 커먼즈 라이센스
Creative Commons License
2013/07/23 00:04 2013/07/23 00:04
Tag // , , ,

댓글을 달아 주세요

  1. 맥도날드 2019/11/14 02:46  address  modify / delete  reply

    맥도날드는 "양측은 앞으로 양측 입장을 대변하거나 이용하고자 하는 제3의 개인 또는 단체에 대해 더 이상 일절 관여하지 않고 어린이의 치료에만 전념하기로 합의했다"며 "해당 사안에 대해 더 이상의 논쟁을 종결키로 했다"고 전했다.

 128*64 Dot Graphic LCD
1. 일단 먼저 사용한 그래픽 LCD는 컨트롤러가 없다.
2. KS108B 드라이버를 사용한다.
3. 컨트롤러가 없고 초기화 과정이 없다.
4. 화면 클리어가 초기화의 전부이다.
5. 화면은 가로로 Y포인트 64개가 2개(총 128포인트)
6. 상단에서 부터 하단으로 (세로방향) 0~7번까지 1페이지라고 하며 0부터 7페이지 까지 총 8페이지 따라서 64Dot가 존재 한다.

명령은 칩셀렉트로 하며 데이터 시트를 참조 한다.
/CS 명령은 LOW 가 해당칩의 Enable이므로 이를 주의 한다.

먼저 H/W에 대한 포트 정의는 헤더파일에서 정의 하엿으며

기존에 윤덕용 교수님의 ATMEGA128완전정복"의 예제에 나온 코드를 이용하였다.

또한 문자 쉬프트(물처럼 흘러가는것) 에 대한 방법을 추가로 삽입하였다.

코드는 IAR용으로 변경되었으며 폰트 데이터는 별도로 첨부한다.





이하 소스 파일

/********************************************* *                                                             * ********************************************** *                   glcd.h                                    * ********************************************** *                                                             * *                            2012.04.18                    * *                                                             * *                        Make by S. Jung                  * *                                                             * *                                                             * **********************************************/ /******************************* < 화면에 점찍는 방법. >   1. 상태읽기 명령으로 대기.-명령어셋 마지막에 딜레이 루틴 잇으므로 무시한다 2. CS0 이나 CS1 중 하나를 ON시킨다 - 그리고자 하는 chip을 선택한다. 3. 상태 읽기 명령으로 대기. 4. 그리고자하는 위치의 페이지를 선택 명령을 내린다. 5. 상태 읽기 명령으로 대기 6. Y 축 선택 명령을 내린다. 7. 상태 읽기 명령으로 대기 -딜레이 루팅으로 대체 8. 데이터 쓰기 명령으로 점을 찍는다. **********************************/   #ifndef __GLCD_H_ #define __GLCD_H_     #define G_LEFT 1 #define G_RIGHT 2 #define G_ALL 3 #define G_NOMAL 0xCC #define G_SHIFT 4 #define  GLCD_DATA_DDR DDRC #define GLCD_DATABUS PORTC   #define  GLCD_CTRL_DDR  DDRA #define GLCD_CTRLBUS PORTA   #define  GLCD_CTRL_CS0(m) m? SETBIT(PORTA, PORT0):CLEARBIT(PORTA, PORT0) #define  GLCD_CTRL_CS1(m) m? SETBIT(PORTA, PORT1):CLEARBIT(PORTA, PORT1) #defineGLCD_CTRL_RST(m) m? SETBIT(PORTA, PORT2):CLEARBIT(PORTA, PORT2) #define  GLCD_CTRL_RW(m)   m? SETBIT(PORTA, PORT3):CLEARBIT(PORTA, PORT3) #define  GLCD_CTRL_D_I(m)  m? SETBIT(PORTA, PORT4):CLEARBIT(PORTA, PORT4) #define  GLCD_CTRL_EN(m) m?   SETBIT(PORTA, PORT5):CLEARBIT(PORTA, PORT5) #define GLCD_LIGHT(m)  m?SETBIT(PORTA,PORT7):CLEARBIT(PORTA,PORT7) void GLCD_Clear_Line(uchar LINE); void GLCD_command(unsigned char signal, unsigned char command); void GLCD_data(unsigned char signal, unsigned char character); void GLCD_Set_Data(unsigned char CS,unsigned char PAGE, unsigned char Y_ADD, unsigned char DATA); void GLCD_Korean(unsigned int Kcode); void GLCD_string(unsigned char x, unsigned char y, char * string); void GLCD_xy(unsigned char x, unsigned char y); void GLCD_xy_row(unsigned char x, unsigned char y, unsigned char row); void GLCD_clear(void);   void GLCD_string_2(unsigned char x,unsigned char y,char *string); //display a string void GLCD_KOREAN_SHIFT(unsigned int Kcode, unsigned char PAGE, unsigned char CHAR_START_POS); void Shift_Character(unsigned char PAGE, char *CHARACTER, int Y_POSISON); void GLCD_ENGLISH_SHIFT(unsigned char Ecode,unsigned char PAGE,unsigned char CHAR_START_POS); void GLCD_Logo(unsigned char DELAY_SEC); extern __flash unsigned char E_font[128][16]; extern __flash unsigned char table_cho[21]; extern __flash unsigned char table_joong[30]; extern __flash unsigned char table_jong[30]; extern __flash unsigned char bul_cho1[22]; extern __flash unsigned char bul_cho2[22]; extern __flash unsigned char bul_jong[22]; extern __flash unsigned char K_font[360][32]; extern __flash unsigned char KS_Table[2350][2]; extern __flash unsigned char logo[1024];         #endif          







#include "board.h" unsigned char xcharacter, ycharacter; // x character(0-3), y character(0-15) unsigned char cursor_flag, xcursor, ycursor; // x and y cursor position(0-3, 0-15) volatile unsigned char Y_POS; void GLCD_Clear_Line(uchar LINE) { GLCD_string(LINE,0,"                "); } void GLCD_command(unsigned char signal,unsigned char command)       /* write a command */ { switch(signal) { case 0xc0: PORTA = ((PORTA&0x84)|0x00); //CS0,1 ,EN = 0 break; case 0x80: PORTA = ((PORTA&0x84)|0x01); break; case 0x40: PORTA = ((PORTA&0x84)|0x02); break; default : break; } PORTC = command; Delay_us(3); PORTA = ((PORTA&0x87)|0x20); //EN1 asm("NOP"); Delay_us(7); } void GLCD_data(unsigned char signal,unsigned char character)        /* write a data */ { switch(signal) { case 0xc0: PORTA = ((PORTA&0x84)|0x10); //CS0,1 ,EN = 0,DI=1 break; case 0x80: PORTA = ((PORTA&0x84)|0x11); break; case 0x40: PORTA = ((PORTA&0x84)|0x12); break; default : break; } PORTC = character; Delay_us(3); PORTA = ((PORTA&0x97)|0x20); asm("NOP"); Delay_us(7); } void GLCD_Set_Data(unsigned char CS,unsigned char PAGE, unsigned char Y_ADD, unsigned char DATA) { unsigned char CS_TEMP; unsigned char F_STATE; switch(CS) { case G_RIGHT: CS_TEMP = 0x80; F_STATE = G_NOMAL; break; case  G_LEFT: CS_TEMP = 0x40;// F_STATE = G_NOMAL; break; case G_ALL: CS_TEMP = 0xC0; F_STATE = G_NOMAL; break; case G_SHIFT: F_STATE = G_SHIFT; break; default: CS_TEMP = FAIL; break; } if ((PAGE<8) && (F_STATE== G_NOMAL) && (Y_ADD<128)) { PAGE|=0xB8; if(Y_ADD>63) //Y_ADD 63넘어가면 Right 화면  자동선택 { GLCD_command(0x80,PAGE); GLCD_command(0x80,0x40+(Y_ADD-64)); GLCD_data(0x80,DATA); //Data 입력 } else { Y_ADD |= 0x40; GLCD_command(CS_TEMP,PAGE); GLCD_command(CS_TEMP,Y_ADD); GLCD_data(CS_TEMP,DATA); //Data 입력 } } else if ((PAGE<8) && (F_STATE== G_SHIFT) && (Y_ADD<128)) { PAGE|=0xB8; if(Y_ADD>63) //Y_ADD 63넘어가면 Right 화면  자동선택 { GLCD_command(0x80,PAGE); GLCD_command(0x80,0x40+(Y_ADD-64)); GLCD_data(0x80,DATA); //Data 입력 } else { Y_ADD |= 0x40; GLCD_command(0x40,PAGE); GLCD_command(0x40,Y_ADD); GLCD_data(0x40,DATA); //Data 입력 } } else { GLCD_string(0,0, "G_SET DATA FAIL");} } void GLCD_clear(void) /* clear GLCD screen */ { volatile unsigned char i, j, x;   //PORTA = ((PORTA&0xA4)); // clear all control signals   GLCD_command(0xC0,0xC0); // CS1,CS2 display position   GLCD_command(0xC0,0x3F); // CS1,CS2 display ON   x = 0xB8;   for(i = 0; i <= 7; i++)     {     GLCD_command(0xC0,x);                     // X start addtess       GLCD_command(0xC0,0x40);                  // Y start address       for(j = 0; j <= 63; j++) GLCD_data(0xC0,0x00); // clear CS1 and CS2 screen       x++;     } } void GLCD_xy(unsigned char x,unsigned char y) /* set English character position */ { xcharacter = x; // x = 0 - 3   ycharacter = y; // y = 0 - 15 } void GLCD_xy_row(unsigned char x,unsigned char y,unsigned char row) /* set character upper/lower row */ { if(row == 0) // if upper row, set Y address     GLCD_command(0xC0,0xB8 + x*2);   else // if lower row, set Y address + 1     GLCD_command(0xC0,0xB8 + x*2 + 1);   if(y <= 7) // if y <= 7, CS1 Y address     GLCD_command(0x40,0x40 + y*8);   else // if y >= 8, CS2 Y address     GLCD_command(0x80,0x40 + (y-8)*8); } void GLCD_English(unsigned char Ecode) /* display a 8x16 Dot English(ASCII) */ { unsigned char i, signal;   GLCD_xy_row(xcharacter,ycharacter,0); // display upper row   if(ycharacter <= 7) // if y <= 7, CS1     signal = 0x40;   else // if y >= 8, CS2     signal = 0x80;   for(i = 0; i <= 7; i++)     GLCD_data(signal,E_font[Ecode][i]);//(signal,pgm_read_byte(&E_font[Ecode][i]));   GLCD_xy_row(xcharacter,ycharacter,1); // display lower row   if(ycharacter <= 7) // if y <= 7, CS1     signal = 0x40;   else // if y >= 8, CS2     signal = 0x80;   for(i = 8; i <= 15; i++)     { if((cursor_flag == 1) && (xcharacter == xcursor) && (ycharacter == ycursor))         GLCD_data(signal,E_font[Ecode][i] | 0x80);//(signal,pgm_read_byte(&E_font[Ecode][i]) | 0x80);       else         GLCD_data(signal,E_font[Ecode][i]);//(signal,pgm_read_byte(&E_font[Ecode][i]));     }   ycharacter++;                                 // go next character position   if(ycharacter == 16)     { ycharacter = 0;       xcharacter++;     } } void GLCD_Korean(unsigned int Kcode) /* display a 16x16 Dot Korean */ { unsigned char i, signal;   unsigned char cho_5bit, joong_5bit, jong_5bit;   unsigned char cho_bul, joong_bul, jong_bul=0, jong_flag;   unsigned int character;   unsigned char Korean_buffer[32]; // 32 byte Korean font buffer   if(ycharacter == 15) // if can not display, go next line     GLCD_English(0x20); // get cho, joong, jong 5 bit   cho_5bit = table_cho[(Kcode >> 10) & 0x001F];//pgm_read_byte(&table_cho[(Kcode >> 10) & 0x001F]);   joong_5bit = table_joong[(Kcode >> 5) & 0x001F];//pgm_read_byte(&table_joong[(Kcode >> 5) & 0x001F]);   jong_5bit = table_jong[Kcode & 0x001F];//pgm_read_byte(&table_jong[Kcode & 0x001F]);   if(jong_5bit == 0) // don't have jongsung     { jong_flag = 0;       cho_bul = bul_cho1[joong_5bit];// pgm_read_byte(&bul_cho1[joong_5bit]);       if((cho_5bit == 1) || (cho_5bit == 16)) joong_bul = 0;       else                                    joong_bul = 1;     }   else // have jongsung     { jong_flag = 1;       cho_bul = bul_cho2[joong_5bit];//pgm_read_byte(&bul_cho2[joong_5bit]);       if((cho_5bit == 1) || (cho_5bit == 16)) joong_bul = 2;       else                                    joong_bul = 3;       jong_bul = bul_jong[joong_5bit];//pgm_read_byte(&bul_jong[joong_5bit]);     }   character = cho_bul*20 + cho_5bit; // copy chosung font   for(i = 0; i <= 31; i++)     Korean_buffer[i] = K_font[character][i];//pgm_read_byte(&K_font[character][i]);   character = 8*20 + joong_bul*22 + joong_5bit; // OR joongsung font   for(i = 0; i <= 31; i++)     Korean_buffer[i] |= K_font[character][i];// pgm_read_byte(&K_font[character][i]);   if(jong_flag == 1) // if jongsung, OR jongsung font     { character = 8*20 + 4*22 +jong_bul*28 + jong_5bit;       for(i = 0; i <= 31; i++)         Korean_buffer[i] |= K_font[character][i];//pgm_read_byte(&K_font[character][i]);           }   GLCD_xy_row(xcharacter,ycharacter,0); // display upper left row   if(ycharacter <= 7) // if y <= 7, CS1     signal = 0x40;   else // if y >= 8, CS2     signal = 0x80;   for(i = 0; i <= 7; i++)     GLCD_data(signal,Korean_buffer[i]);   GLCD_xy_row(xcharacter,ycharacter,1); // display lower left row   if(ycharacter <= 7) // if y <= 7, CS1     signal = 0x40;   else // if y >= 8, CS2     signal = 0x80;   for(i = 16; i <= 23; i++)     { if((cursor_flag == 1) && (xcharacter == xcursor) && (ycharacter == ycursor))          GLCD_data(signal,Korean_buffer[i] | 0x80);       else          GLCD_data(signal,Korean_buffer[i]);     }   ycharacter++;   GLCD_xy_row(xcharacter,ycharacter,0); // display upper right row   if(ycharacter <= 7) // if y <= 7, CS1     signal = 0x40;   else // if y >= 8, CS2     signal = 0x80;   for(i = 8; i <= 15; i++)     GLCD_data(signal,Korean_buffer[i]);   GLCD_xy_row(xcharacter,ycharacter,1); // display lower right row   if(ycharacter <= 7) // if y <= 7, CS1     signal = 0x40;   else // if y >= 8, CS2     signal = 0x80;   for(i = 24; i <= 31; i++)     { if((cursor_flag == 1) && (xcharacter == xcursor) && (ycharacter == (ycursor+1)))          GLCD_data(signal,Korean_buffer[i] | 0x80);       else          GLCD_data(signal,Korean_buffer[i]);     }   ycharacter++;                                 // go next character position   if(ycharacter == 16)     { ycharacter = 0;       xcharacter++;     } } unsigned int KS_code_conversion(unsigned int KSSM) /* convert KSSM(완성형) to KS(조합형) */ {   unsigned char HB, LB;   unsigned int index, KS;   HB = KSSM >> 8;   LB = KSSM & 0x00FF;   if(KSSM >= 0xB0A1 && KSSM <= 0xC8FE)     { index = (HB - 0xB0)*94 + LB - 0xA1;       KS  =  KS_Table[index][0] * 256;//pgm_read_byte(&KS_Table[index][0]) * 256;       KS |=  KS_Table[index][1];// pgm_read_byte(&KS_Table[index][1]);       return KS;     }   else     return 1; } void GLCD_string(unsigned char x,unsigned char y,char *string) //display a string { unsigned char character1;   unsigned int character2;   GLCD_xy(x,y); // x = 0 - 3, y = 0 - 15   while(*string != '\0')      { character1 = *string;          string++; if(character1 < 0x80)          GLCD_English(character1); // display English character        else          { character2 = 256*character1 + (*string & 0xFF);            string++;   character2 = KS_code_conversion(character2); // convert KSSM(완성형) to KS(조합형)            GLCD_Korean(character2); // display Korean character          }      } } void GLCD_string_2(unsigned char x,unsigned char y,char *string) //display a string { unsigned char character1;   unsigned int character2;   //GLCD_xy(x,y); // x = 0 - 3, y = 0 - 15   while(*string != '\0')      { character1 = *string;          string++; if(character1 < 0x80)          GLCD_English(character1); // display English character        else          { character2 = 256*character1 + (*string & 0xFF);            string++;   character2 = KS_code_conversion(character2); // convert KSSM(완성형) to KS(조합형)           // GLCD_KOREAN_SHIFT(character2); // display Korean character          }      } } void GLCD_KOREAN_SHIFT(unsigned int Kcode, unsigned char PAGE, unsigned char CHAR_START_POS) {  unsigned char i, Y_CURSOR,TEMP_VALID;   unsigned char cho_5bit, joong_5bit, jong_5bit;   unsigned char cho_bul, joong_bul, jong_bul=0, jong_flag;   unsigned int character;   unsigned char Korean_buffer[32]; // 32 byte Korean font buffer   unsigned char UP[16];   unsigned char LO[16];       //if(ycharacter == 15) // if can not display, go next line    // GLCD_English(0x20); // get cho, joong, jong 5 bit   cho_5bit = table_cho[(Kcode >> 10) & 0x001F];//pgm_read_byte(&table_cho[(Kcode >> 10) & 0x001F]);   joong_5bit = table_joong[(Kcode >> 5) & 0x001F];//pgm_read_byte(&table_joong[(Kcode >> 5) & 0x001F]);   jong_5bit = table_jong[Kcode & 0x001F];//pgm_read_byte(&table_jong[Kcode & 0x001F]);   if(jong_5bit == 0) // don't have jongsung     { jong_flag = 0;       cho_bul = bul_cho1[joong_5bit];// pgm_read_byte(&bul_cho1[joong_5bit]);       if((cho_5bit == 1) || (cho_5bit == 16)) joong_bul = 0;       else                                    joong_bul = 1;     }   else // have jongsung     { jong_flag = 1;       cho_bul = bul_cho2[joong_5bit];//pgm_read_byte(&bul_cho2[joong_5bit]);       if((cho_5bit == 1) || (cho_5bit == 16)) joong_bul = 2;       else                                    joong_bul = 3;       jong_bul = bul_jong[joong_5bit];//pgm_read_byte(&bul_jong[joong_5bit]);     }   character = cho_bul*20 + cho_5bit; // copy chosung font   for(i = 0; i <= 31; i++)     Korean_buffer[i] = K_font[character][i];//pgm_read_byte(&K_font[character][i]);   character = 8*20 + joong_bul*22 + joong_5bit; // OR joongsung font   for(i = 0; i <= 31; i++)     Korean_buffer[i] |= K_font[character][i];// pgm_read_byte(&K_font[character][i]);   if(jong_flag == 1) // if jongsung, OR jongsung font     { character = 8*20 + 4*22 +jong_bul*28 + jong_5bit;       for(i = 0; i <= 31; i++)         Korean_buffer[i] |= K_font[character][i];//pgm_read_byte(&K_font[character][i]);           } memcpy(&UP,&Korean_buffer[0],16); //상16 memcpy(&LO,&Korean_buffer[16],16);//하16          //(화면,세로페이지,Y point,data) Y_CURSOR = Y_POS; TEMP_VALID  = 127-Y_POS; if(CHAR_START_POS ==0xFF)  //문자 16자리중 시작점이 0이 아닐경우 { if( Y_CURSOR<111) { for(i=0;i<16;i++) { GLCD_Set_Data(G_SHIFT,PAGE,    Y_CURSOR+i,UP[i]); //상 GLCD_Set_Data(G_SHIFT,PAGE+1,Y_CURSOR+i,LO[i]);//하 Y_POS++; } } else { for(i=0;i<TEMP_VALID;i++) { GLCD_Set_Data(G_SHIFT,PAGE,    Y_CURSOR+i,UP[i]); //상 GLCD_Set_Data(G_SHIFT,PAGE+1,Y_CURSOR+i,LO[i]);//하 Y_POS++; } } } else// //문자 16부분중 시작점이 지정된 경우 Y Address 는 0부터 { for (i=0;CHAR_START_POS<16;i++) { GLCD_Set_Data(G_SHIFT,PAGE,    Y_CURSOR+i,UP[CHAR_START_POS]); //상 GLCD_Set_Data(G_SHIFT,PAGE+1,Y_CURSOR+i,LO[CHAR_START_POS]);//하 CHAR_START_POS++; Y_POS++; } }  //한글데이터 32바이트  상단 좌측,상단 우측,하단 좌측,하단 우측 순으로  각 8바이트식 쓰여짐 /* for(signal = 0; signal<8;signal++) { GLCD_Set_Data(G_RIGHT,5,100+signal,Korean_buffer[signal]); //상좌 GLCD_Set_Data(G_RIGHT,6,100+signal,Korean_buffer[signal+16]);//하좌 } for(signal = 0; signal<8;signal++) { GLCD_Set_Data(G_RIGHT,5,108+signal,Korean_buffer[signal+8]);//상우 GLCD_Set_Data(G_RIGHT,6,108+signal,Korean_buffer[signal+24]);//하우 }*/   } void Shift_Character(unsigned char PAGE, char *string, int Y_POSISON) {    unsigned char character1;    unsigned int character2;    unsigned char LOOP, i;    unsigned int POS_CNT = 0;    unsigned int EN = 0, KR = 0, TEMP_SH;    unsigned int STRING_CNT = 0;    if (Y_POSISON > 0x8000) //음수    {       Y_POSISON = Y_POSISON * ( -1);       Y_POS = 0;       i = 1;    }    else    {       Y_POS = (Y_POSISON & 0xFF);       i = 0;    }    while(Y_POS != 127)     {     if(*string != '\0')    {                if (i == 0)          {             character1 = *string;             string++;             STRING_CNT++;             if (character1 < 0x80)             {                GLCD_ENGLISH_SHIFT( character1, PAGE, 0xFF);             }             else             {                character2 = 256 * character1 + (*string & 0xFF);                string++;                STRING_CNT++;                character2 = KS_code_conversion(character2); // convert KSSM(완성형) to KS(조합형)                GLCD_KOREAN_SHIFT(character2, PAGE, 0xFF); // display Korean character             }          }          else          {             character1 = *string;             string++;             STRING_CNT++;             if (character1 < 0x80) //English             {                for (i = 0;i < 8;i++)                {                   POS_CNT++;                   if (i == 7)                   {                      EN += 8;                   }                   if (POS_CNT == Y_POSISON)                   {                      i = 8;                   }                } //영문 포지션 위치 회득                if (POS_CNT == Y_POSISON)                {                   TEMP_SH = EN + KR;                   if (TEMP_SH == 0)                   {                      GLCD_ENGLISH_SHIFT(character1, PAGE, POS_CNT); // display Korean characte                      i = 0;                   }                   else                   {                      if ((POS_CNT - TEMP_SH) == 0)                      {                         i = 0;                      }                      else                      {                         GLCD_ENGLISH_SHIFT(character1, PAGE, POS_CNT - TEMP_SH); // display Korean characte                         i = 0;                      }                   }                }                else                {}             }             else //힌글             {                for (i = 0;i < 16;i++)                {                   POS_CNT++;                   if (i == 15)                   {                      KR += 16;                   }                   if (POS_CNT == Y_POSISON)                   {                      i = 16;                   }                }                if (POS_CNT == Y_POSISON)                {                   character2 = 256 * character1 + (*string & 0xFF);                   string++;                   STRING_CNT++;                   character2 = KS_code_conversion(character2); // convert KSSM(완성형) to KS(조합형)                   TEMP_SH = EN + KR;                   if (TEMP_SH == 0)                   {                      GLCD_KOREAN_SHIFT(character2, PAGE, POS_CNT); // display Korean characte                      i = 0;                   }                   else                   {                      if ((POS_CNT - TEMP_SH) == 0)                      {                         i = 0;                      }                      else                      {                         GLCD_KOREAN_SHIFT(character2, PAGE, POS_CNT - TEMP_SH); // display Korean characte                         i = 0;                      }                   }                }                else                {                   string++; //다음문자로 넘어감.                   STRING_CNT++;                }             }          }          }    else    { for (LOOP= 0 ;LOOP< STRING_CNT;LOOP++)     { string--;     }     STRING_CNT = 0;    } }     } void GLCD_ENGLISH_SHIFT(unsigned char Ecode,unsigned char PAGE,unsigned char CHAR_START_POS) { unsigned char i; unsigned char Y_CURSOR =0, TEMP_VALID; Y_CURSOR = Y_POS; TEMP_VALID  = 127-Y_POS; if(CHAR_START_POS ==0xFF)  //문자 16자리중 시작점이 0이 아닐경우 { if( Y_CURSOR<119) { for(i=0;i<8;i++) { GLCD_Set_Data(G_SHIFT,PAGE,Y_POS,E_font[Ecode][i]);//(signal,pgm_read_byte(&E_font[Ecode][i])); GLCD_Set_Data(G_SHIFT,PAGE+1,Y_POS,E_font[Ecode][i+8]);//(signal,pgm_read_byte(&E_font[Ecode][i])); Y_POS++; } } else { for(i=0;i<TEMP_VALID;i++) { GLCD_Set_Data(G_SHIFT,PAGE,Y_POS,E_font[Ecode][i]);//(signal,pgm_read_byte(&E_font[Ecode][i])); GLCD_Set_Data(G_SHIFT,PAGE+1,Y_POS,E_font[Ecode][i+8]);//(signal,pgm_read_byte(&E_font[Ecode][i])); Y_POS++; } } } else// //문자 16부분중 시작점이 지정된 경우 Y Address 는 0부터 { for (i=0;CHAR_START_POS<8;i++) { GLCD_Set_Data(G_SHIFT,PAGE,Y_POS,E_font[Ecode][CHAR_START_POS]);//(signal,pgm_read_byte(&E_font[Ecode][i])); GLCD_Set_Data(G_SHIFT,PAGE+1,Y_POS,E_font[Ecode][CHAR_START_POS+8]);//(signal,pgm_read_byte(&E_font[Ecode][i])); CHAR_START_POS++; Y_POS++; } } } void GLCD_Logo(unsigned char DELAY_SEC) { unsigned char i,j; for (i=0;i<8;i++) { GLCD_command(0xc0,0xb8+(i)); GLCD_command(0x40,0x40); for(j=0;j<=63;j++) { GLCD_data(0x40,logo[i+j*8]); } GLCD_command(0x80,0x40); for(j=64;j<=127;j++) { GLCD_data(0x80,logo[i+j*8]); } } for (i=0;i<DELAY_SEC;i++) { Delay_ms(1000); } }
크리에이티브 커먼즈 라이센스
Creative Commons License
2012/05/02 00:51 2012/05/02 00:51

댓글을 달아 주세요

[CORTEX-M3]MDK New Project

from Firmware 2012/04/03 23:39

하기 내용은 개발보드 CD에 들어있던 내용이다.

Tistory 태그: (새 창으로 열기),(새 창으로 열기),(새 창으로 열기),(새 창으로 열기),(새 창으로 열기)

As one of the ARM development tools, the MDK is extremely powerful in programming function. The follow introduction shows how to use MDK to start a new project and program STM32 devices.

  1. Organize the project documents.
    Create a new Folder "Project" at any site, and create a new subfolder "Lib" for depositing the library files, "MDK_Project" as the MDK main program folder, "User" folder for depositing the user's own program files in the directory.
  2. Put relevant files to the project documents.

    Put relevant files into "Lib" folder:

    Folder
    Explanation

    STM32F10x_StdPeriph_Driver
    StdPeriph_Driver

    CM3
    Cortex-M3 Core files

    startup
    Start Configure

    STM32F10x
    stm32f10x.h,system_stm32f10x.c,system_stm32f10x.h STM32 clock files

    Put user's own program files to "User" folder,such as: main.c,stm32f10x_conf.h,stm32f10x_it.c,stm32f10x_it.h.
    STM32F10x_StdPeriph_Template:stm32f10x_conf.h,stm32f10x_it.c,stm32f10x_it.h Firmware library Configure file and Interrupt Configure files.

  3. Establish and set up MDK project.

    Open MDK and start a new MDK project, and save it in the "MDK_Project" file, then choose the corresponding chip part number.
    Project_new_selmcu

    It is generally to choose "No" for whether loading the MDK example program.
    Project_new_startcode

    Choose "Manage Components" to manage the project folders.
    Project_new_manage

    Create the folder as shown in the figure, and then click OK!
    Project_new_manage2

    Double click the folder to load related documents.
    Project_new_addfile

    Right click the "Taget1" to start setting the project. The red marked places in the Figure 2 should be carefully set;
    The first marked place refers to whether the preprocessing macro definition program use stm32 firmware library or not, and the defined device type, the exact device type can be found in the stm32f10x.h file.

    • STM32F10X_LD: STM32 Low density devices
    • STM32F10X_LD_VL: STM32 Low density Value Line devices
    • STM32F10X_MD: STM32 Medium density devices
    • STM32F10X_MD_VL: STM32 Medium density Value Line devices
    • STM32F10X_HD: STM32 High density devices
    • STM32F10X_HD_VL: STM32 High density value line devices
    • STM32F10X_XL: STM32 XL-density devices
    • STM32F10X_CL: STM32 Connectivity line devices

The second marked place refers to the .h file path, and there will be a system error warning if it is wrong set.

Project_new_settings

Choose the Debugger. (Use ST-Link here)
Project_new_seltools
Project_new_seltools2

=========================================================================================

If use the Ulink2, it should choose Device Size. just as what the following figures show:
Choose the 'ULINK Cortex Debugger', and click 'Settings'.
Project_new_Ulink1

Set the 'Port' as 'JTAG' or 'SWD' in the Debug page, and the 'Max Clock' as well. Just as what's marked in the picture below.
Project_new_Ulink2

Click the 'Flash Download' page, and click the 'Add' button to enter the 'Device Size' options page.
Project_new_Ulink3

For example, if choose the STM32F103ZE MCU, please select the 'STM32F10x High-density Flash', then click 'Add' to add it into the project, and turn back to the previous page and press 'OK' to finish the device type setting.
Project_new_Ulink4

Click the 'Utilities' to set the 'Use Target Driver for Flash Programming' as 'ULINK Cortex Debugger', then click 'OK' to finish the project.
Project_new_Ulink5

 

Now, the new project has completely set up! To view, pls click here.

크리에이티브 커먼즈 라이센스
Creative Commons License
2012/04/03 23:39 2012/04/03 23:39

댓글을 달아 주세요

[Cortex-M3]GPIO_Control

from Firmware 2012/03/27 22:42

먼저 KEIL컴파일러를 사용하였으며
현제 KEIL에서 프로젝터 생성에 지속적으로 실패하여
예제프로그램을 불러와 Main.c 파일 내용을 주석처리 한다음에 사용하였다.
기존에 TI(구 Luminary Micro사)의 Coretex-M3 LM3S8962 의 Datasheet보다
ST사의 Datasheet가 좀더 복잡한것 같다.

아무튼 간에 GPIO를 컨트롤 하기 위해서는 Coretex-M3의 경우 IO PORT에
 클럭을 Enable 해주어야 한다.

기존 AVR 8bit MCU 같은 경우는 PORT DIRECTION만 설정하면 바로 사용할수 있어서 편했는데
이게 전력소모랑 연관되서 그런건지 아직 자세한건 모르겠지만 꽤나 불편하다.

일단 Datasheet의 Memory Map을 파악을 해야하는데 이게 매우 중요하다.

Memory Map도 모르고 내부구조의 이해도 없이 API 만 가져다 쓰는건 그닥이라 Register에 직접 Access하는 쪽이 훨씬 맘에든다 (사실 API를 분석해서 이해하는게 내부 구조 이해해서 레지스터 제어하는것보다 더 어렵다 ㄷㄷㄷ, 이게 다 AVR 때문인듯 -_-;)

또한 Register 직접 Access경우 단순 PORT ON OFF시에 약 3배의 차이가 나기 때문에 고속 Signal 처리할일은 없지만 아무튼 그렇다.- 오실로 스코프로 찍어서 확인해 보세요~ㅋ

ST사의 STM32F103시리즈의 메모리 맵은 하기 그림과 같다,

사용자 삽입 이미지
사용자 삽입 이미지


여기서 RCC Control (0x4002.1000) 어드레스로 가면 APB2ENR 레지스터가 있다
요 레지스터 내부에는 GPIO들에게 클럭을 공급하는 설정을 핤후가 있다.
 
사용자 삽입 이미지
사용자 삽입 이미지

여기서 원하는포트에게 클럭을 공급한다.
나는 GPIOF를 선정하여 Enalbe 하였다.
이후 GPIO FPORT에서 Direction 설정을 해야하는데 이는
GPIOF_CRH, GPIO_CRL 레지스터에서 할수 있다.
여기서 CRL부분은 0번부터 7번 포트까지
CRH 레지스터는 8번부터 15번 포트까지 Direction을 설정 할수가 있다
사용자 삽입 이미지

 
사용자 삽입 이미지

여기서 일단 주의할점은 Reset Value에 주의하자
나는 처음에 (*(volatile unsigned long*)어드레스) |= 0x33000000;
과 같이 OR연산으로 무심결에 집어넣었다가 LED가 안켜지길래 에뮬레이터로 확인해보니
해당 어드레스에 저장된 값이 0x77444444값이 나오더라 ㄷㄷㄷㄷ (이게다 AVR때문임 -대부분 ATmega 시리즈는 Reset Value가 0이다)
일단 내부에 CNF2개 비트에서 인풋 아웃풋 모드로 기능이 나누어지며 풀업, 플로팅 인풋, 아날라그모드, 특수기능 풀업다운, 오픈드레인 상태로 설정할수 있으며 CNF레지스터 뒤에 MODE 레지스터 2비트가 따라 다니는데 이는 Direction과 Clock 속도를 설정할수 있다. CNF,MODE 비트레지스터 뒤의 숫자는 해당 포트의 포트 번호에 따른 기능 설정이다.
사용자 삽입 이미지

이후 몇번 포트를 High로 출력할지 LOW로 출력할지 결정한다.
사용자 삽입 이미지


여기서 설정을 다 끝낸후 Source 코드는 아래와 같다.

(*(volatile unsigned long*)0x40021018) |= 0x00000080; //RCC_APB2ENR - PORTF CLOCK인가

(*(volatile unsigned long*)0x40011c00) = 0x33000000 ; //GPIOx_CRL
 
while(1)
{ 
(*(volatile unsigned long*)0x40011c0C) |= 0x000000F0;//(GPIO_ODR Register(Output Setting Reg)
//(*(volatile unsigned long *)0x40011c10) =0x80; //GPIOx_BSRR Register (ODR corresponding Reg)

 Delay(0xfffff);
 
//(*(volatile unsigned long *)0x40011c10) = (0x80 <<16);
 
 

(*(volatile unsigned long*)0x40011c0C) = 0x00000000;

 Delay(0xfffff);
 }



 

이후 디버깅 화면은 하단 그림과 같다 J-Link를 이용하였다.

사용자 삽입 이미지
크리에이티브 커먼즈 라이센스
Creative Commons License
2012/03/27 22:42 2012/03/27 22:42

댓글을 달아 주세요

상기의 내용은 위 동영상에 나온 코드를 적용하여 만들었으며
CLCD Level Graph 의 경우 Source 코드 내부의 void LCD_Level_Graph(SELECT_LINE,START_POS,WANT_BAR_NUMBER,WANT_PERCENT,SHOW_PERCENT_NUM_FLAG) 함수를 참조하기 바람.

크리에이티브 커먼즈 라이센스
Creative Commons License
2012/03/23 22:53 2012/03/23 22:53
Tag //

댓글을 달아 주세요

GPS-AVR-PC

from Firmware 2011/12/26 00:42
현재 GPS에서 시리얼로 제공되는 정보중에

$GPGGA 정보만 뽑아서 Tiny OS 구조체로 바꾸기 위해 코드 설정

GPS는 9600bps 이고 현제 AVR 에서 PC로 뿌리는 전송속도도 9600bps로 맞추어 놨음

GPS TX 속도에 맞에 AVR수신단( UART0)의

UBRR0L과 UBRR0H를 설정하고

AVR의 TX영역은 사용자가 받기 원하는 BPS값을 설정하기 위해  UBRR1L과 UBRR1H값을 수정하면 된다.

다음 아래의 소스코드는 GPGGA 관련 정보만 GPS에서 뽑아 쓰기 위한 코드이고 Tiny OS 메시지 구조체로 변경은 아직 하지 않았음.

GPS에서 송신단자  TX --10KOhm--(+5V)를  걸고 TX선은 AVR의 USART0번 수신(RX)단에 물렸음

                           ┌--------------------- [AVR-Rx]
  GND-------GPS--- TX-----10kohm--- -┐
    VCC-------└---------------------------┘


gps-avr-pc 간 원하는 전송속도를 내기 위한 bps는

UBRR 을 계산하여 넣어주어야한다 해당 공식이 있지만 이를 헤더파일내에 공식으로 define 하였다.
 
UBRRL과 UBRRH를 설정 하기 위해서 message.h 헤더파일내

BAUD_RATE 값에 원하는 전송속도만로 define 해주고

사용하는 클록을 CPU_CLOCK에 define
하면 된다

현재 사용한 외부 클럭은  8Mh이고  만약 보드에 16Mhz의 크리스탈을 사용할경우 16000000 으로 변경하면됨.













GPS만 단순히 시리얼 통신을 하게 될경우에 다음과 같이 주루루륵 많은 정보가 뜬다
위성이 몇개 잡혔는디 뭐 어쩌구 저쩌구
GPS RAW 데이터 분석 방법은 http://drkein.tistory.com/113(새 창으로 열기) 참조

사용자 삽입 이미지







AVR을 거쳐서 다음과 같이  GPGGA에 관한 정보만 출력 된다.

사용자 삽입 이미지



본 소스 파일에서 LED는 어떤 역할을 하는 것이 아니라 디버깅용으로 사용된것임

인터럽트 함수로 제대로 분기 하는지 혹은 송신단에서 데이터가 정상적으로 보내지는지 표시하는것으로 나타냄

LED 단어가 들어간 모든 부분은 주석처리 하고 컴파일 하셔도 무방합니다.

컴파일러는 Win-AVR을 사용하였음.

해당소스는 마음대로 사용하셔도 좋습니다.


크리에이티브 커먼즈 라이센스
Creative Commons License
2011/12/26 00:42 2011/12/26 00:42
Tag // , ,

댓글을 달아 주세요

<< previous 1 2 next >>