#include #include #include "stm32f1xx.h" #include "main.h" // This variable is used by some CMSIS functions uint32_t SystemCoreClock=8000000; // Milliseconds counter volatile uint32_t systick_count=0; // Interrupt handler for the system timer void SysTick_Handler(void) { systick_count++; } // Write standard output to the serial port 1 int _write(int file, char *ptr, int len) { for (int i=0; iSR & USART_SR_TXE)); USART1->DR = *ptr++; } return len; } void init_io() { // Enable Port A, B, C and alternate functions SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN); // Disable JTAG to free to free PA15, PB3 and PB4 MODIFY_REG(AFIO->MAPR, AFIO_MAPR_SWJ_CFG, AFIO_MAPR_SWJ_CFG_JTAGDISABLE); // Configure the serial Port 1 SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN); // Enable MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF9 + GPIO_CRH_MODE9, GPIO_CRH_CNF9_1 + GPIO_CRH_MODE9_1); // PA9=Output for alternate function USART1->CR1 = USART_CR1_UE + USART_CR1_TE; // Enable transmitter (no receiver) USART1->BRR = (SystemCoreClock / 115200); // Set baud rate //USART1->BRR = (SystemCoreClock / 160000); // Set baud rate // getestet mit cutecom // PC13 = Output for the red LED MODIFY_REG(GPIOC->CRH, GPIO_CRH_CNF13 + GPIO_CRH_MODE13, GPIO_CRH_MODE13_0); // MODIFY_REG(REG, CLEARMASK, SETMASK) } void init_gpio() { // -------------------- GPIOx_CRx bits -------------------- #define ANALOG 0 /* analoger Eingang (oder Ausgang?) */ #define IN 4 /* digitaler Eingang, floating (default after reset) */ #define IN_PUPD 8 /* digitaler Eingang, Pullup/down je nach GPIOx_ODR */ #define OUT_PP_10 1 /* out, push-pull, 10 MHz */ #define OUT_PP_2 2 /* out, push-pull, 2 MHz */ #define OUT_PP_50 3 /* out, push-pull, 50 MHz */ #define OUT_OD_10 5 /* out, OpenDrain, 10 MHz */ #define OUT_OD_2 6 /* out, OpenDrain, 2 MHz */ #define OUT_OD_50 7 /* out, OpenDrain, 50 MHz */ #define ALT_PP_10 9 /* Alternativ-Funktion, push-pull, 10 MHz */ #define ALT_PP_2 10 /* Alternativ-Funktion, push-pull, 2 MHz */ #define ALT_PP_50 11 /* Alternativ-Funktion, push-pull, 50 MHz */ #define ALT_OD_10 13 /* Alternativ-Funktion, OpenDrain, 10 MHz */ #define ALT_OD_2 14 /* Alternativ-Funktion, OpenDrain, 2 MHz */ #define ALT_OD_50 15 /* Alternativ-Funktion, OpenDrain, 50 MHz */ // MODIFY_REG(REG, CLEARMASK, SETMASK) -- set gewinnt //MODIFY_REG(GPIOA->CRL, 15<< 0, OUT_PP_10 << 0); // Port A - Bit 0 //MODIFY_REG(GPIOA->CRL, 15<< 4, OUT_PP_10 << 4); // Port A - Bit 1 //MODIFY_REG(GPIOA->CRL, 15<< 8, OUT_PP_10 << 8); // Port A - Bit 2 //MODIFY_REG(GPIOA->CRL, 15<<12, OUT_PP_10 << 12); // Port A - Bit 3 //MODIFY_REG(GPIOA->CRL, 15<<16, OUT_PP_10 << 16); // Port A - Bit 4 MODIFY_REG(GPIOA->CRL, 15<<20, ALT_PP_10 << 20); // Port A - Bit 5 (SPI1) //MODIFY_REG(GPIOA->CRL, 15<<24, OUT_PP_10 << 24); // Port A - Bit 6 MODIFY_REG(GPIOA->CRL, 15<<28, ALT_PP_10 << 28); // Port A - Bit 7 (SPI1) //MODIFY_REG(GPIOA->CRH, 15<< 0, OUT_PP_10 << 0); // Port A - Bit 8 //MODIFY_REG(GPIOA->CRH, 15<< 4, OUT_PP_10 << 4); // Port A - Bit 9 //MODIFY_REG(GPIOA->CRH, 15<< 8, OUT_PP_10 << 8); // Port A - Bit 10 //MODIFY_REG(GPIOA->CRH, 15<<12, OUT_PP_10 << 12); // Port A - Bit 11 //MODIFY_REG(GPIOA->CRH, 15<<16, OUT_PP_10 << 16); // Port A - Bit 12 //MODIFY_REG(GPIOA->CRH, 15<<20, OUT_PP_10 << 20); // Port A - Bit 13 //MODIFY_REG(GPIOA->CRH, 15<<24, OUT_PP_10 << 24); // Port A - Bit 14 //MODIFY_REG(GPIOA->CRH, 15<<28, OUT_PP_10 << 28); // Port A - Bit 15 //MODIFY_REG(GPIOB->CRL, 15<< 0, OUT_PP_10 << 0); // Port B - Bit 0 //MODIFY_REG(GPIOB->CRL, 15<< 4, OUT_PP_10 << 4); // Port B - Bit 1 //MODIFY_REG(GPIOB->CRL, 15<< 8, OUT_PP_10 << 8); // Port B - Bit 2 //MODIFY_REG(GPIOB->CRL, 15<<12, OUT_PP_10 << 12); // Port B - Bit 3 //MODIFY_REG(GPIOB->CRL, 15<<16, OUT_PP_10 << 16); // Port B - Bit 4 //MODIFY_REG(GPIOB->CRL, 15<<20, OUT_PP_10 << 20); // Port B - Bit 5 //MODIFY_REG(GPIOB->CRL, 15<<28, OUT_PP_10 << 28); // Port B - Bit 7 //MODIFY_REG(GPIOB->CRH, 15<< 0, OUT_PP_10 << 0); // Port B - Bit 8 //MODIFY_REG(GPIOB->CRH, 15<< 4, OUT_PP_10 << 4); // Port B - Bit 9 //MODIFY_REG(GPIOB->CRH, 15<< 8, OUT_PP_10 << 8); // Port B - Bit 10 //MODIFY_REG(GPIOB->CRH, 15<<12, OUT_PP_10 << 12); // Port B - Bit 11 MODIFY_REG(GPIOB->CRH, 15<<16, OUT_PP_10 << 16); // Port B - Bit 12 (CS for SPI1 and SPI2, software controlled) MODIFY_REG(GPIOB->CRH, 15<<20, ALT_PP_10 << 20); // Port B - Bit 13 (SPI2) //MODIFY_REG(GPIOB->CRH, 15<<24, OUT_PP_10 << 24); // Port B - Bit 14 MODIFY_REG(GPIOB->CRH, 15<<28, ALT_PP_10 << 28); // Port B - Bit 15 (SPI2) MODIFY_REG(GPIOC->CRH, 15<<20, OUT_PP_10 << 20); // Port C - Bit 13 (LED on the Bluepill Board) //MODIFY_REG(GPIOC->CRH, 15<<24, OUT_PP_10 << 24); // Port C - Bit 14 //MODIFY_REG(GPIOC->CRH, 15<<28, OUT_PP_10 << 28); // Port C - Bit 15 } int main(void) { test_spi2(); // never returns ( SPI setup aufgeräumt, ohne Systick, ohne RS232) // Initialize I/O pins init_io(); // Initialize system timer SysTick_Config(SystemCoreClock/1000); puts("Hello World1"); WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BR13); // LED on // verschiedene Testroutinen //test_rs232(); // never returns test_spi(); // never returns while(1) { // LED Off WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BS13); // Delay 1 second uint32_t start=systick_count; while (systick_count-start<500); // LED On WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BR13); puts("Hello World5"); // Delay 1 second start=systick_count; while (systick_count-start<1000); //ITM_SendChar('a'); // gibt ein Zeichen auf der SWO Leitung aus -> Prg hängt wenn das an ist } } // ************************************************************************************************************* // *** *** // *** Testroutinen *** // *** *** // ************************************************************************************************************* // Testet UART-Read and write void test_rs232() { uint8_t data; int led_state=0; uint32_t start; // Configure the serial Port 1 SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN); // Enable MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF9 + GPIO_CRH_MODE9 , GPIO_CRH_CNF9_1 + GPIO_CRH_MODE9_1); // PA9 =Output for alternate function // den A10 kann man auch auf Power-on-default lassen (Input floating) MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF10+ GPIO_CRH_MODE10, GPIO_CRH_CNF10_1 ); // PA10=Input with pull up/down -- so geht es //MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF10+ GPIO_CRH_MODE10, GPIO_CRH_CNF10_0 ); // PA10=Input floating -- so geht es (das ist aber sowieso der Power-on defaultwert) // GPIO_CRH_CNF10 beide bits gesetzt !!!1! // GPIO_CRH_CNF10_0 bit 0 gesetzt // GPIO_CRH_CNF10_1 bit 1 gesetzt SET_BIT(GPIOA->ODR,1<<10); // PA10 pull-up einschalten (=Ausgang auf high setzen wenn der Pin auf Ausgang geschaltet wäre) USART1->BRR = (SystemCoreClock / 115200); // Set baud rate //USART1->CR1 = USART_CR1_UE + USART_CR1_TE; // Enable transmitter (no receiver) USART1->CR1 = USART_CR1_UE + USART_CR1_TE + USART_CR1_RE; // Enable transmitter and receiver // PC13 = Output for the red LED MODIFY_REG(GPIOC->CRH, GPIO_CRH_CNF13 + GPIO_CRH_MODE13, GPIO_CRH_MODE13_0); // MODIFY_REG(REG, CLEARMASK, SETMASK) -- set gewinnt puts("Hello World3\n"); USART1->DR = 65; // ein "A" senden start=systick_count; while(1) { if ((USART1->SR & USART_SR_RXNE)) // wenn ein Byte empfangen wurde { data = USART1->DR; USART1->DR = data+1; // modifiziert zurück senden um funktion zu bestätigen } //while(!(USART1->SR & USART_SR_TXE)); // USART1->DR = *ptr++; //puts("Hello World5"); if ((systick_count-start)>500) // Zeit ist um { //USART1->DR = 66; // ein "B" senden if (led_state) { WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BS13); // LED Off start=systick_count; led_state=0; ITM_SendChar('a'); // gibt ein Zeichen auf der SWO Leitung aus ITM_SendChar('\n'); // Zeilenumbruch im STM32 Cube Programmer SWV Viewer } else { WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BR13); // LED on start=systick_count; led_state=1; } } } } void test_spi() { uint16_t data=0; int led_state=0; uint32_t start; // Enable Port A, B, C and alternate functions SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN); // Enable SPI1 SET_BIT(RCC->APB1ENR, RCC_APB1ENR_SPI2EN); // Enable SPI2 init_gpio(); // set all ports to GPIO and alternate functions // ToDo: vor oder nach dem SPI setup?!?? SET_BIT(SPI1->CR1, SPI_CR1_DFF); // 16 bit per transfer SET_BIT(SPI1->CR1, SPI_CR1_MSTR); // Master mode SET_BIT(SPI1->CR1, SPI_CR1_BR_2); // clock div 32 / RM0008 p.743 //SET_BIT(SPI1->CR1, SPI_CR1_BR_0); // clock div 4 / RM0008 p.743 SET_BIT(SPI1->CR1, SPI_CR1_SPE); // SPI enable SET_BIT(SPI2->CR1, SPI_CR1_DFF); // 16 bit per transfer SET_BIT(SPI2->CR1, SPI_CR1_MSTR); // Master mode SET_BIT(SPI2->CR1, SPI_CR1_BR_2); // clock div 32 / RM0008 p.743 //SET_BIT(SPI2->CR1, SPI_CR1_BR_0); // clock div 4 / RM0008 p.743 SET_BIT(SPI2->CR1, SPI_CR1_SPE); // SPI enable puts("Hello World SPI 3 \n"); ITM_SendChar('0'); // gibt ein Zeichen auf der SWO Leitung aus start=systick_count; while(1) { if (0)//((SPI1->SR & SPI_SR_TXE)) // wenn ein Byte gesendet werden kann { SPI1->DR=0x1234; // send 16 bit word SPI2->DR=0x1234; // send 16 bit word } if ((systick_count-start)>500) // Zeit ist um { //USART1->DR = 66; // ein "B" senden if (led_state) { WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BS13); // LED Off start=systick_count; led_state=0; ITM_SendChar('a'); // gibt ein Zeichen auf der SWO Leitung aus // write 2x 16 bit on SPI2 and 1x 16bit on SPI1 WRITE_REG(GPIOB->BSRR,GPIO_BSRR_BR12); // PB12 low ( Chip select for SPI) while (!(SPI1->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write //while (!(SPI2->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write // bei SPI2 hängt der hier ewig SPI2->DR=0x55ff; // send 16 bit word SPI1->DR=data; // send 16 bit word while (!(SPI1->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write //while (!(SPI2->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write // bei SPI2 hängt der hier ewig SPI2->DR=0x300f; // send 16 bit word SPI1->DR=data; // send 16 bit word while ( (SPI1->SR & SPI_SR_BSY)); // busy wait for SPI transfer to be finished while ( (SPI2->SR & SPI_SR_BSY)); // busy wait for SPI transfer to be finished WRITE_REG(GPIOB->BSRR,GPIO_BSRR_BS12); // PB12 high ( Chip select for SPI) data++; ITM_SendChar('b'); // gibt ein Zeichen auf der SWO Leitung aus ITM_SendChar('\n'); // Zeilenumbruch im STM32 Cube Programmer SWV Viewer } else { WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BR13); // LED on start=systick_count; led_state=1; } } } } // void test_spi2() { uint16_t data=0; int led_state=0; // Enable Port A, B, C and alternate functions SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN); SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN); // Enable SPI1 SET_BIT(RCC->APB1ENR, RCC_APB1ENR_SPI2EN); // Enable SPI2 init_gpio(); // set all ports to GPIO and alternate functions // ToDo: vor oder nach dem SPI setup?!?? SET_BIT(SPI1->CR1, SPI_CR1_DFF); // 16 bit per transfer SET_BIT(SPI1->CR1, SPI_CR1_MSTR); // Master mode SET_BIT(SPI1->CR1, SPI_CR1_BR_2); // clock div 32 / RM0008 p.743 ( bei 8MHz Takt sind das 250kHz) //SET_BIT(SPI1->CR1, SPI_CR1_BR_0); // clock div 4 / RM0008 p.743 SET_BIT(SPI1->CR1, SPI_CR1_SPE); // SPI enable SET_BIT(SPI2->CR1, SPI_CR1_DFF); // 16 bit per transfer SET_BIT(SPI2->CR1, SPI_CR1_MSTR); // Master mode SET_BIT(SPI2->CR1, SPI_CR1_BR_2); // clock div 32 / RM0008 p.743 //SET_BIT(SPI2->CR1, SPI_CR1_BR_0); // clock div 4 / RM0008 p.743 SET_BIT(SPI2->CR1, SPI_CR1_SPE); // SPI enable ITM_SendChar('1'); // gibt ein Zeichen auf der SWO Leitung aus while(1) { if (led_state) { WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BS13); // LED Off led_state=0; } else { WRITE_REG(GPIOC->BSRR,GPIO_BSRR_BR13); // LED on led_state=1; } ITM_SendChar('a'); // gibt ein Zeichen auf der SWO Leitung aus // write 2x 16 bit on SPI2 and 2x 16bit on SPI1 WRITE_REG(GPIOB->BSRR,GPIO_BSRR_BR12); // PB12 low ( Chip select for SPI) while (!(SPI1->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write //while (!(SPI2->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write // bei SPI2 hängt der hier ewig (außer beim ersten Aufruf) SPI2->DR=0x55ff; // send 16 bit word SPI1->DR=data; // send 16 bit word while (!(SPI1->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write //while (!(SPI2->SR & SPI_SR_TXE)); // busy wait for TX buffer ready to write // bei SPI2 hängt der hier ewig SPI2->DR=0x300f; // send 16 bit word SPI1->DR=data; // send 16 bit word while ( (SPI1->SR & SPI_SR_BSY)); // busy wait for SPI transfer to be finished while ( (SPI2->SR & SPI_SR_BSY)); // busy wait for SPI transfer to be finished (SPI2 hängt hier nicht) WRITE_REG(GPIOB->BSRR,GPIO_BSRR_BS12); // PB12 high ( Chip select for SPI) data++; ITM_SendChar('2'); // gibt ein Zeichen auf der SWO Leitung aus ITM_SendChar('\n'); // Zeilenumbruch im STM32 Cube Programmer SWV Viewer for (uint32_t j=0; j < 2000UL * 500; j++) // delay ca. 500ms (at 8MHz CPU Clock) { __NOP(); } } }