from: https://eroro.tistory.com/488
https://github.com/blalor/avr-softuart
위 사이트에 나와있는 소스코드를 STM32F103에서 동작하도록 변경
9600bps에 맞췄습니다만 본인이 사용하는 클럭 설정이나 다른 코어라면 코어의 처리 속도등을 고려해서 Timer의 발생 시간을 조절해주어야 합니다.
계산해보면 1/9600 = 0.00010416… 이므로 오차율 감안하고 104us정도 나오도록 오실로스코프로 계산하면서 맞춰주면 될 것 같습니다.
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
#include <stdarg.h> #include <stdio.h> #define SU_TRUE 1 #define SU_FALSE 0 // 1 Startbit, 8 Databits, 1 Stopbit = 10 Bits/Frame #define TX_NUM_OF_BITS (10) volatile static unsigned char flag_tx_busy; volatile static unsigned char timer_tx_ctr; volatile static unsigned char bits_left_in_tx; /* ! mt: was type uchar - this was wrong */ volatile static unsigned short internal_tx_buffer; #define UARTTXPORT GPIOA #define UARTTXPIN GPIO_Pin_9 #define set_tx_pin_high() GPIO_SetBits(UARTTXPORT, UARTTXPIN) #define set_tx_pin_low() GPIO_ResetBits(UARTTXPORT, UARTTXPIN) extern void TIM2_IRQHandler(void); void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); Tim2_IRQ(); } } void Tim2_IRQ(void) { unsigned char tmp; // Transmitter Section if ( flag_tx_busy == SU_TRUE ) { tmp = timer_tx_ctr; if ( --tmp == 0 ) { // if ( --timer_tx_ctr <= 0 ) if ( internal_tx_buffer & 0x01 ) { set_tx_pin_high(); } else { set_tx_pin_low(); } internal_tx_buffer >>= 1; tmp = 3; // timer_tx_ctr = 3; if ( --bits_left_in_tx == 0 ) { flag_tx_busy = SU_FALSE; } } timer_tx_ctr = tmp; } } void gpio_init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* Enable the GPIO_LED clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* mt: set to high to avoid garbage on init */ set_tx_pin_high(); /* Configure Led pin as output */ GPIO_InitStruct.GPIO_Pin = UARTTXPIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(UARTTXPORT, &GPIO_InitStruct); flag_tx_busy = SU_FALSE; } void timer_init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 70 - 1; // Timer/Count2 Clock = 36Mhz / (35 + 1) = 1Mhz = 1 usec TIM_TimeBaseStructure.TIM_Prescaler = 35; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // Ä«¿îÅ͸ðµåµ¿ÀÛ TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* TIM2 counter enable */ TIM_Cmd(TIM2, ENABLE); /* TIM IT enable */ TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void softuart_init( void ) { gpio_init(); /* 9600bps Setting */ timer_init(); } unsigned char softuart_transmit_busy( void ) { return ( flag_tx_busy == SU_TRUE ) ? 1 : 0; } void softuart_putchar( const char ch ) { while ( flag_tx_busy == SU_TRUE ) { ; // wait for transmitter ready // add watchdog-reset here if needed; } // invoke_UART_transmit timer_tx_ctr = 3; bits_left_in_tx = TX_NUM_OF_BITS; internal_tx_buffer = ( ch << 1 ) | 0x200; flag_tx_busy = SU_TRUE; } void softuart_puts( const char *s ) { while ( *s ) { softuart_putchar( *s++ ); } } void softuart_puts_P(char *string) { while(*string != '\0') softuart_putchar(*(string++)); } void softuart_print(const char *fmt,...) { char string[256]; va_list ap; va_start(ap,fmt); vsprintf(string,fmt,ap); va_end(ap); softuart_puts_P(string); } void main(void) { softuart_init(); softuart_print("\r\nSoftuart Demo-Application Start \r\n"); } |