Comments to source code

This commit is contained in:
Andreas Mieke 2018-04-03 17:18:28 +02:00
parent d109bae8d7
commit 9a18bd88f0
22 changed files with 286 additions and 122 deletions

View file

@ -2,34 +2,38 @@
void init_bma(void)
{
// Init GPIOB and I2C1 clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// SCL
// Change default values for SCL port, init port
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &gpio);
// SDA
// Change default values for SDA port, init port
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);
// Create i2c struct, fill it with default values, change clock to 400 kHz and init I2C
I2C_InitTypeDef i2c;
I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &i2c);
// Enable I2C1 interface
I2C_Cmd(I2C1, ENABLE);
}
void run_bma(float acc_f[3])
{
int16_t acc[3];
// Select first register address to read
// Send first register address to read
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, BMA_ADDR, I2C_Direction_Transmitter);
@ -38,39 +42,42 @@ void run_bma(float acc_f[3])
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
// Start Rx transmission
I2C_GenerateSTART(I2C1, ENABLE);
I2C_AcknowledgeConfig(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, BMA_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// X LSB
// Read X LSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[0] = (I2C_ReceiveData(I2C1) & 0xC0) >> 6;
// X MSB
// Read X MSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[0] = (I2C_ReceiveData(I2C1) & 0xFF) << 2 | (acc[0] & 0x0003);
if(acc[0] & 0x0200) acc[0] |= 0xFC00;
// Y LSB
// Read Y LSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[1] = (I2C_ReceiveData(I2C1) & 0xC0) >> 6;
// Y MSB
// Read Y MSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[1] = (I2C_ReceiveData(I2C1) & 0xFF) << 2 | (acc[1] & 0x0003);
if(acc[1] & 0x0200) acc[1] |= 0xFC00;
// Z LSB
// Read Z LSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[2] = (I2C_ReceiveData(I2C1) & 0xC0) >> 6;
// Z MSB
// Read Z MSB
I2C_AcknowledgeConfig(I2C1, DISABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[2] = (I2C_ReceiveData(I2C1) & 0xFF) << 2 | (acc[2] & 0x0003);
if(acc[2] & 0x0200) acc[2] |= 0xFC00;
// Stop condition
I2C_GenerateSTOP(I2C1, ENABLE);
// Calculate float values, with a maximum amplitude of 2.0g, as described in the datasheet
acc_f[0] = 2.0f * ((float)acc[0]/512);
acc_f[1] = 2.0f * ((float)acc[1]/512);
acc_f[2] = 2.0f * ((float)acc[2]/512);
@ -78,6 +85,7 @@ void run_bma(float acc_f[3])
void deinit_bma(void)
{
// Disable I2C1 and de-init it
I2C_Cmd(I2C1, DISABLE);
I2C_DeInit(I2C1);
}

View file

@ -7,9 +7,9 @@
#include "stm32f10x_i2c.h" // Keil::Device:StdPeriph Drivers:I2C
#define BMA_ADDR (uint8_t)0x70 // 0b01110000
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
void init_bma(void);
void run_bma(float acc_f[3]);

View file

@ -16,38 +16,49 @@ char colors[COLORS][7] = {
void init_display(void)
{
// Init GPIOB and USART3 clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PB10 to alternate function push pull
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB, &gpio);
// Set PB11 to input floating
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOB, &gpio);
// Create usart struct and set USART3 to 9600 baud
USART_InitTypeDef usart;
USART_StructInit(&usart);
usart.USART_BaudRate = 9600;
USART_Init(USART3, &usart);
// Init USART clock
USART_ClockInitTypeDef usartclock;
USART_ClockStructInit(&usartclock);
USART_ClockInit(USART3, &usartclock);
// Enable USART3
USART_Cmd(USART3, ENABLE);
}
void run_display(void)
{
// String to store command
char cmd[16], *cptr;
cptr = cmd;
// Fill string with every color from colors[]
sprintf(cmd, "cls %s\xFF\xFF\xFF", colors[i++]);
// If the last color is reached, begin again
if (i == COLORS) i = 0;
// Send character for character to USART3 (the display)
while(*cptr) {
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
USART_SendData(USART3, *cptr++);
@ -56,12 +67,16 @@ void run_display(void)
void deinit_display(void)
{
// Reset command
char *cmd = "rest\xFF\xFF\xFF";
// Reset the display after the test finishes
while(*cmd) {
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
USART_SendData(USART3, *cmd++);
}
// Wait till the last character is sent
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
// Then disable USART3 again
USART_Cmd(USART3, DISABLE);
USART_DeInit(USART3);
}

View file

@ -5,6 +5,7 @@ volatile uint32_t *EEPROMSTick, EEPROMSTickCur;
uint8_t load_byte(uint16_t eeprom_addr)
{
uint8_t data;
// Send address to read from
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
@ -14,20 +15,24 @@ uint8_t load_byte(uint16_t eeprom_addr)
I2C_SendData(I2C1, (eeprom_addr & 0x00FF));
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Switch to Rx mode
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// Load byte
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
I2C_GenerateSTOP(I2C1, ENABLE);
// Return data byte
return data;
}
void write_byte(uint16_t eeprom_addr, uint8_t data)
{
// Send address to write to
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
@ -37,11 +42,12 @@ void write_byte(uint16_t eeprom_addr, uint8_t data)
I2C_SendData(I2C1, (eeprom_addr & 0x00FF));
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Send data byte
I2C_SendData(I2C1, data);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
// Wait 5 ms to satisfy the write cycle time of the EEPROM
EEPROMSTickCur = *EEPROMSTick;
while((*EEPROMSTick - EEPROMSTickCur) <= 50); // 5ms write cycle, see datasheet param 17
return;
@ -49,27 +55,31 @@ void write_byte(uint16_t eeprom_addr, uint8_t data)
void init_eeprom(volatile uint32_t *SysTickCnt)
{
// Enable GPIOB and I2C1 cloc
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// SCL
// Set PB6 to alternate function push pull (SCL)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &gpio);
// SDA
// Set PB7 to alternate function open drain (SDA)
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);
// Set I2C clock to 400 kHz
I2C_InitTypeDef i2c;
I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &i2c);
// Enable I2C1 and save SysTick pointer
I2C_Cmd(I2C1, ENABLE);
EEPROMSTick = SysTickCnt;
return;
@ -77,6 +87,7 @@ void init_eeprom(volatile uint32_t *SysTickCnt)
void run_eeprom(uint8_t *success)
{
// Write some data to some addresses and check if the date matches after a read, if not, return
uint8_t set, read;
*success = 0;
set = 0xAA;
@ -111,12 +122,14 @@ void run_eeprom(uint8_t *success)
write_byte(0x0005, set);
read = load_byte(0x0005);
if (set != read) return;
// If everything matches, set success to true and then return
*success = 1;
return;
}
void deinit_eeprom(void)
{
// Disable I2C1
I2C_Cmd(I2C1, DISABLE);
I2C_DeInit(I2C1);
return;

View file

@ -7,9 +7,9 @@
#include "stm32f10x_i2c.h" // Keil::Device:StdPeriph Drivers:I2C
#define EEPROM_ADDR (uint8_t)0xA0 // 0b10100000
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
void init_eeprom(volatile uint32_t *SysTickCnt);
void run_eeprom(uint8_t *success);

View file

@ -2,29 +2,36 @@
void init_esp(void)
{
// Enable GPIOa and USART2 clocks
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PB2 to alternate function push pull (Tx)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOA, &gpio);
// Set PB3 to input floating (Rx)
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &gpio);
// Create usart struct and init USART2 to 115 200 baud
USART_InitTypeDef usart;
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
USART_Init(USART2, &usart);
// Init USART2 clock
USART_ClockInitTypeDef usartclock;
USART_ClockStructInit(&usartclock);
USART_ClockInit(USART2, &usartclock);
// Init NVIC for USART2 RXNE to see stuff sent to the TCP server. The ISR is in main.c
NVIC_InitTypeDef nvic;
nvic.NVIC_IRQChannel = USART2_IRQn;
nvic.NVIC_IRQChannelCmd = ENABLE;
@ -33,11 +40,13 @@ void init_esp(void)
NVIC_Init(&nvic);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// Enable USART2
USART_Cmd(USART2, ENABLE);
}
void esp_wait()
{
// Wait some time so the ESP can execute the commands sent
int i, j;
for(j=0;j<500;j++) {
for(i=0;i<65536;i++);
@ -45,6 +54,7 @@ void esp_wait()
}
void send_str(char *str) {
// Sends a string over UART
while(*str) {
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
USART_SendData(USART2, *str++);
@ -53,23 +63,31 @@ void send_str(char *str) {
void run_esp(void)
{
// Restore the ESP to defaults, then wait
send_str("AT+RESTORE\r\n");
esp_wait();
// Print out the current mode
send_str("AT+CWMODE?\r\n");
esp_wait();
// Set mode to access point
send_str("AT+CWMODE=2\r\n");
esp_wait();
// Reset
send_str("AT+RST\r\n");
esp_wait();
// Enable access point
send_str("AT+CIPMUX=1\r\n");
esp_wait();
// Start TCP server on port 2526
send_str("AT+CIPSERVER=1,2526\r\n");
esp_wait();
// Print out the current IP address
send_str("AT+CIPAP_CUR?\r\n");
}
void deinit_esp(void)
{
// Disable the interrupt, then disable USART2
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
USART_Cmd(USART2, DISABLE);
USART_DeInit(USART2);

View file

@ -2,6 +2,7 @@
void USART_SendString(USART_TypeDef *USARTx, char *str)
{
// Sends a string, character for character, over the specified UART
while (*str) {
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
USART_SendData(USARTx, *str++);
@ -10,35 +11,44 @@ void USART_SendString(USART_TypeDef *USARTx, char *str)
void init_all(void)
{
// Enable all GPIO and USART clocks needed for USART1, 2 and 3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// Create gpio struct and fill it with defaults
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PA9 to alternate function push pull (Tx)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA, &gpio);
// Same for PA2
gpio.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOA, &gpio);
// Same for PB10
gpio.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB, &gpio);
// Set PA10 to input floating (Rx)
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &gpio);
// Same for PA3
gpio.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &gpio);
// Same for PB11
gpio.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOB, &gpio);
// Create usart struct and set baud rate to 115 200, init all three USARTs with this baud rate
USART_InitTypeDef usart;
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
@ -46,16 +56,19 @@ void init_all(void)
USART_Init(USART2, &usart);
USART_Init(USART3, &usart);
// Enable USART clocks
USART_ClockInitTypeDef usartclock;
USART_ClockStructInit(&usartclock);
USART_ClockInit(USART1, &usartclock);
USART_ClockInit(USART2, &usartclock);
USART_ClockInit(USART3, &usartclock);
// Enable the USARTs
USART_Cmd(USART1, ENABLE);
USART_Cmd(USART2, ENABLE);
USART_Cmd(USART3, ENABLE);
// Enable the SysTick with T = 1 ms
RCC_ClocksTypeDef clocks;
RCC_GetClocksFreq(&clocks);
SysTick_Config(clocks.HCLK_Frequency/1000 - 1); // SysTick T=1ms
@ -63,6 +76,7 @@ void init_all(void)
void send_welcome(void)
{
// Send a welcome message to all three USARTs
USART_SendString(USART1, "\x1B[2J\x1B[0;0HManufacturing test software, press space...\r\n");
USART_SendString(USART2, "\x1B[2J\x1B[0;0HManufacturing test software, press space...\r\n");
USART_SendString(USART3, "\x1B[2J\x1B[0;0HManufacturing test software, press space...\r\n");
@ -71,10 +85,14 @@ void send_welcome(void)
unsigned int wait_for_start(void)
{
uint8_t data;
// Runs until space has been pressed on one UART
for(;;) {
// Checks if USART1 receive register is not empty
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {
data = USART_ReceiveData(USART1);
// Checks if space has been pressed
if (data == ' ') {
// Disable the other UARTs and return 1 as this is the used UART
USART_Cmd(USART2, DISABLE);
USART_Cmd(USART3, DISABLE);
USART_DeInit(USART2);
@ -85,9 +103,12 @@ unsigned int wait_for_start(void)
USART_DeInit(USART1);
}
}
// Checks if USART2 receive register is not empty
if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == SET) {
data = USART_ReceiveData(USART2);
// Checks if space has been pressed
if (data == ' ') {
// Disable the other UARTs and return 2 as this is the used UART
USART_Cmd(USART1, DISABLE);
USART_Cmd(USART3, DISABLE);
USART_DeInit(USART1);
@ -98,9 +119,12 @@ unsigned int wait_for_start(void)
USART_DeInit(USART2);
}
}
// Checks if USART3 receive register is not empty
if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == SET) {
data = USART_ReceiveData(USART3);
// Checks if space has been pressed
if (data == ' ') {
// Disable the other UARTs and return 3 as this is the used UART
USART_Cmd(USART1, DISABLE);
USART_Cmd(USART2, DISABLE);
USART_DeInit(USART1);
@ -117,11 +141,15 @@ unsigned int wait_for_start(void)
unsigned int wait_for_test(USART_TypeDef *USARTx)
{
int data;
// Blocks until something is pressed
for(;;)
{
// Checks if receive register is not empty
if (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == SET) {
data = (int)USART_ReceiveData(USARTx);
if ((data > 0x09 && data <= 0x30) || data > 0x39) return 1;
// If data is out of range return 1 (no test)
if ((data > 0x09 && data <= 0x30) || data > 0x39) return 1;
// Else return the correct test id
return (data >= 0x30) ? data - 0x30 : data;
}
}
@ -130,10 +158,14 @@ unsigned int wait_for_test(USART_TypeDef *USARTx)
unsigned int get_test(USART_TypeDef *USARTx)
{
int data;
// Checks if receive register is not empty
if (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == SET) {
data = (int)USART_ReceiveData(USARTx);
if ((data > 0x09 && data <= 0x30) || data > 0x39) return 1;
// If data is out of range return 1 (no test)
if ((data > 0x09 && data <= 0x30) || data > 0x39) return 1;
// Else return the correct test id
return (data >= 0x30) ? data - 0x30 : data;
}
// If nothing has been sent to the UART, return 0 (test not changed)
return 0;
}

View file

@ -2,16 +2,20 @@
void init_ledswitch(void)
{
// Init GPIOA and GPIOC clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// Create gpio struct and fill it with defaults
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set the LED ports to push pull
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOC, &gpio);
// Set the switch ports to input pull up
gpio.GPIO_Mode = GPIO_Mode_IPU;
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
GPIO_Init(GPIOA, &gpio);
@ -20,7 +24,9 @@ void init_ledswitch(void)
void run_ledswitch(uint8_t *switches)
{
// Read switches and shift it to represent a 8 bit number
*switches = (GPIO_ReadInputData(GPIOA) & 0x000F) | ((GPIO_ReadInputData(GPIOA) & 0x01E0) >> 1);
// Write that 8 bit number correctly shifted again to the LEDs
GPIO_Write(GPIOC, ((*switches & 0xE0) << 2) | ((*switches & 0x1F) << 1));
return;
}

View file

@ -17,33 +17,43 @@ USART_TypeDef *used_usart;
void SysTick_Handler()
{
// Increment SysTickCnt
SysTickCnt++;
}
void USART2_IRQHandler()
{
// Print received data to the used UART
USART_SendData(used_usart, USART_ReceiveData(USART2));
}
void wait(uint32_t ms)
{
uint32_t SysTickCntHold = SysTickCnt;
while((SysTickCnt - SysTickCntHold) <= ms);
// Wait the specified time in milliseconds
uint32_t SysTickCntHold = SysTickCnt;
while((SysTickCnt - SysTickCntHold) <= ms);
}
int main()
{
char buffer[1024];
// Create test and next test enum, set both to not init
enum test_t current_test = test_not_init, next_test = test_not_init;
// Create interface enum, set it to none
enum iface_t control_interface = interface_none;
// Endless main loop
for (;;) {
// Switch the interface
switch (control_interface) {
// If no interface has been specified, init everything, print welcome and wait for specification
case interface_none:
init_all();
send_welcome();
control_interface = (enum iface_t)wait_for_start();
// Switch thru the return value
switch (control_interface) {
// Set used_usart to the right one, depeinding on the selected interface
case interface_usart1:
used_usart = USART1;
break;
@ -53,45 +63,61 @@ int main()
case interface_usart3:
used_usart = USART3;
break;
default:
// If there is no one, set it back to none and do everything again
default:
control_interface = interface_none;
break;
}
break;
// If a interface is specified look up the test to du
case interface_usart1:
case interface_usart2:
case interface_usart3:
// Switch thru the tests
switch(current_test) {
// If not inited, set the test to none
case test_not_init:
current_test = test_none;
break;
// If none, print main menu and wait for a test to be selected
case test_none:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HManufacturing test software, Version " VERSION "\r\n\r\n\
\tTo run tests, enter one of the following numbers:\r\n\t\t[2]\tBMA\r\n\t\t[3]\tNE555/LFU/IR\r\n\
\t\t[4]\tLEDs and Switches\r\n\t\t[5]\tESP\r\n\t\t[6]\tEEPROM\r\n\t\t[7]\tRGB LED\r\n\t\t[8]\tPiezo\r\n\t\t[9]\tDisplay\r\n\r\nWaiting for your selection... ");
current_test = (enum test_t)wait_for_test(used_usart);
break;
// Else print the page for the selected test and then run it
case test_bma:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HBMA Test\r\n\r\nThis tests the correct function\
of the used BMA gyroscope as well as I2C port 1. Below you should see the current acceleration values printed\
for the X, Y and Z axis. Where the Z axis should show something around 1g, as this is the gravitational\
acceleration on the Earth, of course this value is lower if you run this program on the moon!\r\n\r\n\
To return to the main menu press a button.\r\n\r\n\r\n");
// Init the test and create variables if needed
init_bma();
float accs[3];
// Test loop
for(;;) {
// Run the test (here: get the acceleration avlues)
run_bma(accs);
// Print the values to the interface
sprintf(buffer, "\x1B[K\rX: % 02.5f, Y: % 02.5f, Z: % 02.5f", accs[0], accs[1], accs[2]);
USART_SendString(used_usart, buffer);
// Check if there is a new test (or main menu) selected
next_test = (enum test_t)get_test(used_usart);
if (next_test != test_not_init) {
// If the new test differs from the current one, change the current one so that in the next run of the main loop the right test gets executed
current_test = next_test;
// DeInit the peripherals used for the test
deinit_bma();
// Leave the test loop, let the main mloop continue to run
break;
}
// Wait some time to be able to read the returned values
wait(50);
}
break;
// Run NE555/LFU/IR test, for more information about the executed commands see BMA test (above)
case test_ne555:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HNE555/LFU/IR Test\r\n\r\nThis tests the correct function\
of the NE555/LFU/IR on the board. The currently selected frequency should be printed below!\r\n\r\n\
@ -111,6 +137,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// Run LED/Switch test, for more information about the executed commands see BMA test (above)
case test_led:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HLED/Switch Test\r\n\r\nThis tests the correct function\
of the switches and the leds on the board. The currently selected leds are shown hexadecimal below!\r\n\r\n\
@ -130,6 +157,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// Run ESP test, for more information about the executed commands see BMA test (above)
case test_esp:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HESP Test\r\n\r\nThis tests the correct function\
of the ESP module on the board. The ESP should open a WLAN AP!\r\n\r\n\
@ -148,6 +176,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// Run EEPROM test, for more information about the executed commands see BMA test (above)
case test_eeprom:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HEEPROM Test\r\n\r\nThis tests the correct function\
of the EEPROM on the board. The test will run and show an OK or NOK below!\r\n\r\n\
@ -170,6 +199,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// Run RGB LED test, for more information about the executed commands see BMA test (above)
case test_rgb:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HRGB LED Test\r\n\r\nThis tests the correct function\
of the RGB LED and it's I2C driver on the board!\r\n\r\n\
@ -186,6 +216,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// Run Piezo test, for more information about the executed commands see BMA test (above)
case test_piezo:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HPiezo Test\r\n\r\nThis tests the correct function\
of the Piezo on the board. You should hear the frequency printed below!\r\n\r\n\
@ -204,6 +235,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// Run display test, for more information about the executed commands see BMA test (above)
case test_display:
USART_SendString(used_usart, "\x1B[2J\x1B[0;0HDisplay Test\r\n\r\nThis tests the correct function\
of the Display on the board. You should see text printed on the display!\r\n\r\n\
@ -222,6 +254,7 @@ To return to the main menu press a button.\r\n\r\n\r\n");
wait(50);
}
break;
// If test does not exist, go to main menu
default:
current_test = test_none;
break;

View file

@ -1,8 +1,10 @@
#ifndef MAIN_H
#define MAIN_H
// Define program version
#define VERSION "0.1.0"
// Define interfaces which can be used
enum iface_t {
interface_none = 0,
interface_usart1,
@ -10,6 +12,7 @@ enum iface_t {
interface_usart3
};
// Define available tests
enum test_t {
test_not_init = 0,
test_none = 1,

View file

@ -5,11 +5,14 @@ uint8_t old_state;
void init_ne555(volatile uint32_t *SysTickCnt)
{
// Enable GPIOb clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PB0 to input floating
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOB, &gpio);
@ -23,15 +26,18 @@ void run_ne555(float *freq)
uint8_t state;
*freq = 0.0f;
NE555STickCur = *NE555STick;
// Run for one second
while((*NE555STick - NE555STickCur) <= 1000)
{
state = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0);
// If the state changes low -> high or high -> low increment freq and save state
if (state != old_state)
{
(*freq)++;
old_state = state;
}
}
// Divide freq by two to get the frequency
*freq /= 2;
return;
}

View file

@ -4,11 +4,14 @@ volatile uint32_t *PiezoSTick, PiezoSTickCur, Freq;
void init_piezo(volatile uint32_t *SysTickCnt)
{
// Enable GPIOB clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PB0 to output push pull
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOB, &gpio);
@ -21,10 +24,13 @@ void run_piezo()
{
uint8_t pstate = 0x0;
PiezoSTickCur = *PiezoSTick;
// Run for one second
while((*PiezoSTick - PiezoSTickCur) <= 1000)
{
Freq = *PiezoSTick;
// Wait for 1 millisecond
while((*PiezoSTick - Freq) <= 1);
// Toggle output
if (pstate) {
pstate = ~pstate;
GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);

View file

@ -1,6 +1,7 @@
#include "rgb.h"
#include "main.h"
// Define registers of the RGB LED driver
typedef enum {
RGB_SHUTDOWN = 0x00,
RGB_MAXCUR,
@ -15,14 +16,17 @@ typedef enum {
void rgb_send_command(uint8_t data)
{
// Generate start condition and transmit address
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, RGB_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// Send data
I2C_SendData(I2C1, data);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Generate stop condition
I2C_GenerateSTOP(I2C1, ENABLE);
return;
@ -30,36 +34,42 @@ void rgb_send_command(uint8_t data)
void init_rgb(void)
{
// Enable GPIOB anf I2C1 clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// Create gpio struct and fill it with default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// SCL
// SET PB6 to alternate function push pull (SCL)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &gpio);
// SDA
// Set PB7 to alternate function open drain (SDA)
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);
// Init I2C1 to 400 kHz
I2C_InitTypeDef i2c;
I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &i2c);
// Enable I2C1 driver
I2C_Cmd(I2C1, ENABLE);
// LED actually allows 40mA, but driver only hanbdles around 30
// Set the max current the driver should allow
// LED actually allows 40mA, but driver only handles around 30
rgb_send_command(0x3F);
return;
}
void run_rgb(void)
{
// Set random colors for 100 ms each
rgb_send_command(0x5F);
wait(100);
rgb_send_command(0x7F);
@ -83,6 +93,7 @@ void run_rgb(void)
void deinit_rgb(void)
{
// Disable I2C1
I2C_Cmd(I2C1, DISABLE);
I2C_DeInit(I2C1);
return;

View file

@ -2,6 +2,7 @@
void bluetooth_init(void)
{
// Init USART1
usart1_init();
}
@ -9,6 +10,8 @@ void bluetooth_send_gyro_data(uint8_t X, uint8_t Y, uint8_t Z)
{
char __str[128] = {0};
char *str = __str;
// Print data comma-sperated to String
sprintf(str, "%d,%d,%d\r\n", X, Y, Z);
// Send string over USARt to the bluetooth module
USART_SendString(USART1, str);
}

View file

@ -1,9 +1,9 @@
#include "bma.h"
#define BMA_ADDR (uint8_t)0x70 // 0b01110000
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
void bma_init(void)
{
@ -13,7 +13,7 @@ void bma_init(void)
void bma_get_acc(uint8_t *X, uint8_t *Y, uint8_t *Z)
{
int16_t acc[3];
// Select first register address to read
// Send first register address to read
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, BMA_ADDR, I2C_Direction_Transmitter);
@ -22,39 +22,42 @@ void bma_get_acc(uint8_t *X, uint8_t *Y, uint8_t *Z)
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
// Start Rx transmission
I2C_GenerateSTART(I2C1, ENABLE);
I2C_AcknowledgeConfig(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, BMA_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// X LSB
// Read X LSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[0] = (I2C_ReceiveData(I2C1) & 0xC0) >> 6;
// X MSB
// Read X MSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[0] = (I2C_ReceiveData(I2C1) & 0xFF) << 2 | (acc[0] & 0x0003);
if(acc[0] & 0x0200) acc[0] |= 0xFC00;
// Y LSB
// Read Y LSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[1] = (I2C_ReceiveData(I2C1) & 0xC0) >> 6;
// Y MSB
// Read Y MSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[1] = (I2C_ReceiveData(I2C1) & 0xFF) << 2 | (acc[1] & 0x0003);
if(acc[1] & 0x0200) acc[1] |= 0xFC00;
// Z LSB
// Read Z LSB
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[2] = (I2C_ReceiveData(I2C1) & 0xC0) >> 6;
// Z MSB
// Read Z MSB
I2C_AcknowledgeConfig(I2C1, DISABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
acc[2] = (I2C_ReceiveData(I2C1) & 0xFF) << 2 | (acc[2] & 0x0003);
if(acc[2] & 0x0200) acc[2] |= 0xFC00;
// Stop condition
I2C_GenerateSTOP(I2C1, ENABLE);
// Calculate display values, with a maximum amplitude of 2.0g, as described in the datasheet
*X = (acc[0]/4) + 128;
*Y = (acc[1]/4) + 128;
*Z = (acc[2]/4) + 128;

View file

@ -5,12 +5,15 @@ uint8_t running = 0;
void USART3_IRQHandler(void)
{
// HAndle only USART3 RXNE interrupt
if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) {
// Get display state
state = (disp_state_t)((USART_ReceiveData(USART3) & 0x00FF) - '0');
if (state > 4) {
state = DISP_STATE_NONE;
}
}
// Set running according to pressed button
if (state == DISP_STATE_START) {
running = 1;
} else if (state == DISP_STATE_PAUSE) {
@ -20,8 +23,10 @@ void USART3_IRQHandler(void)
void disp_init(void)
{
// Init USART3
usart3_init();
// Init USART3 interrupt
NVIC_InitTypeDef nvic;
nvic.NVIC_IRQChannel = USART3_IRQn;
nvic.NVIC_IRQChannelCmd = ENABLE;
@ -30,11 +35,13 @@ void disp_init(void)
NVIC_Init(&nvic);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
// Disable display till startup is complete
disp_disable();
}
disp_state_t disp_get_last_state(void)
{
// Returns the last state (which we got form the interrupt)
disp_state_t tmp = state;
state = DISP_STATE_NONE;
return tmp;
@ -44,16 +51,19 @@ void disp_send_gyro_data(uint8_t X, uint8_t Y, uint8_t Z)
{
char __str[128] = {0};
char *str = __str;
// Print gyro data to the display
sprintf(str, "add 1,0,%d\xFF\xFF\xFF" "add 1,1,%d\xFF\xFF\xFF" "add 1,2,%d\xFF\xFF\xFF", X, Y, Z);
USART_SendString(USART3, str);
}
void disp_disable(void)
{
// Disable (dim to 0%) display
USART_SendString(USART3, "dim=0\xFF\xFF\xFF");
}
void disp_enable(void)
{
// Enable display again (dim to 100%)
USART_SendString(USART3, "dim=100\xFF\xFF\xFF");
}

View file

@ -6,6 +6,7 @@
#include "io.h"
#include "stdio.h"
// Display states/buttons
typedef enum uint8_t {
DISP_STATE_NONE = 0x00,
DISP_STATE_PAUSE,

View file

@ -2,21 +2,24 @@
extern volatile uint32_t SysTickCnt;
// EEPROM addresse
#define EEPROM_ADDR (uint8_t)0xA0 // 0b10100000
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
// ---- Vendor address part
// --- User address part
// - Keep free for R/W bit (set by I2C_Send7bitAddress())
uint32_t last_write_tick = 0;
void eeprom_init(void)
{
// Init I2C1
i2c1_init();
}
void eeprom_read(uint16_t address, uint8_t *data, uint16_t length)
{
uint16_t cur_pos;
// Send address of EEPROM and start address on EEPROM
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
@ -26,12 +29,14 @@ void eeprom_read(uint16_t address, uint8_t *data, uint16_t length)
I2C_SendData(I2C1, (address & 0x00FF));
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Switch to receive mode
I2C_GenerateSTART(I2C1, ENABLE);
I2C_AcknowledgeConfig(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// Read all bytes and disable ACK on last byte
for(cur_pos = 0; cur_pos < length; cur_pos++) {
if(cur_pos == length - 1) {
I2C_AcknowledgeConfig(I2C1, DISABLE);
@ -40,6 +45,7 @@ void eeprom_read(uint16_t address, uint8_t *data, uint16_t length)
data[cur_pos] = I2C_ReceiveData(I2C1);
}
// Send stop condition
I2C_GenerateSTOP(I2C1, ENABLE);
}
@ -49,9 +55,13 @@ void eeprom_write(uint16_t address, uint8_t *data, uint16_t length)
uint16_t cur_pos = 0;
address = address & 0xFFA0;
// If more than one page is needed, cycle over the pages
for(cur_page = 0; cur_page <= ((length-1)/64); cur_page++) {
// Wait 5 ms for the write cycle (see datasheet)
while((SysTickCnt - last_write_tick) <= 5);
// Send start condition
I2C_GenerateSTART(I2C1, ENABLE);
// Send EEPROM address and start address of data to send
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, EEPROM_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
@ -60,11 +70,13 @@ void eeprom_write(uint16_t address, uint8_t *data, uint16_t length)
I2C_SendData(I2C1, (address & 0x00FF));
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Send max 64 bytes (1 page) of data
for(; (cur_pos < length) && (cur_pos%64 <= 63); cur_pos++) {
I2C_SendData(I2C1, data[cur_pos]);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
// Generate stop condition and calculate address of next page (if needed)
I2C_GenerateSTOP(I2C1, ENABLE);
address += 0x0040;
last_write_tick = SysTickCnt;

View file

@ -6,104 +6,125 @@ uint8_t usart3_inited = 0;
void i2c1_init(void)
{
// If I2C1 is already inited, do nothing
if (i2c1_inited == 1) {
return;
}
// Enable GPIOB and I2C1 clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// Create gpio struct and fill default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// SCL
// Set PB6 to alternate function push pull (SCL)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &gpio);
// SDA
// Set PB7 to alternate function open drain (SDA)
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);
// Set I2C1 clock to 400 kHz
I2C_InitTypeDef i2c;
I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &i2c);
// Enable I2C1
I2C_Cmd(I2C1, ENABLE);
i2c1_inited = 1;
}
void usart1_init(void)
{
// If USART1 is inited, do nothing
if (usart1_inited == 1) {
return;
}
// Enable GPIOA and USART1 clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// Create gpio struct and fill default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// TxD
// Set PA9 to alternate function push pull (TxD)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA, &gpio);
// RxD
// Set PA10 to input floating (RxD)
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &gpio);
// Set USART1 clock to 115 200 baud
USART_InitTypeDef usart;
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
USART_Init(USART1, &usart);
// Init USART1 clocks
USART_ClockInitTypeDef usartclock;
USART_ClockStructInit(&usartclock);
USART_ClockInit(USART1, &usartclock);
// Enable USART1
USART_Cmd(USART1, ENABLE);
usart1_inited = 1;
}
void usart3_init(void)
{
// If USART3 is inited, do nothing
if (usart3_inited == 1) {
return;
}
// Enable GPIOB and USART3 clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// Create gpio struct and fill default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// TxD
// Set PB10 to alternate function push pull (TxD)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB, &gpio);
// RxD
// Set PB11 to input floating (RxD)
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOB, &gpio);
// Set USART3 clock to 115 200 baud
USART_InitTypeDef usart;
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
USART_Init(USART3, &usart);
// Init USART3 clocks
USART_ClockInitTypeDef usartclock;
USART_ClockStructInit(&usartclock);
USART_ClockInit(USART3, &usartclock);
// Enable USART3
USART_Cmd(USART3, ENABLE);
usart3_inited = 1;
}
void USART_SendString(USART_TypeDef *USARTx, char *str)
{
// Send a string, byte by byte over the specified USART
while (*str) {
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
USART_SendData(USARTx, *str++);

View file

@ -7,46 +7,63 @@
int main()
{
// Variables needed
disp_state_t current_state = DISP_STATE_NONE;
uint8_t X, Y, Z, running = 0;
uint8_t bX[BUFFER_SIZE] = {128}, bY[BUFFER_SIZE] = {128}, bZ[BUFFER_SIZE] = {128};
uint8_t bX[BUFFER_SIZE] = {128}, bY[BUFFER_SIZE] = {128}, bZ[BUFFER_SIZE] = {128}; // 128 is the 'zero' line in the display, so the array is initzialized to 128
uint16_t buffer_pos = 0;
// Init everything we need
disp_init();
systick_init();
bma_init();
eeprom_init();
bluetooth_init();
// Enable display
disp_enable();
// Main loop
for (;;) {
// Check if button is pressed
current_state = disp_get_last_state();
if(current_state == DISP_STATE_START) {
// If start button set running to true
running = 1;
} else if(current_state == DISP_STATE_PAUSE) {
// On pause set running to false
running = 0;
}
// Only read and send data if display is actually running
if(running == 1) {
// Get accelerations
bma_get_acc(&X, &Y, &Z);
// Put them into the buffer (for save/recall)
bX[buffer_pos] = X;
bY[buffer_pos] = Y;
bZ[buffer_pos] = Z;
// Send data to display and bluetooth
disp_send_gyro_data(X, Y, Z);
bluetooth_send_gyro_data(X, Y, Z);
// Increment buffer position
buffer_pos++;
if(buffer_pos == BUFFER_SIZE) {
// If buffer size is reached, return to 0 (ringbuffer)
buffer_pos = 0;
}
}
if(current_state == DISP_STATE_SAVE) {
// On save, send the three arrays to the EEPROM
eeprom_write(0x0000, bX, BUFFER_SIZE);
eeprom_write(0x0400, bY, BUFFER_SIZE);
eeprom_write(0x0800, bZ, BUFFER_SIZE);
}
if(current_state == DISP_STATE_RECALL) {
// On recall read the three arrays from EEPROM
eeprom_read(0x0000, bX, BUFFER_SIZE);
eeprom_read(0x0400, bY, BUFFER_SIZE);
eeprom_read(0x0800, bZ, BUFFER_SIZE);
// Also update display and bluetooth completely with the new data in the buffer
for(uint16_t i = 0; i < BUFFER_SIZE; i++) {
disp_send_gyro_data(bX[i], bY[i], bZ[i]);
bluetooth_send_gyro_data(bX[i], bY[i], bZ[i]);

View file

@ -4,20 +4,24 @@ volatile uint32_t SysTickCnt;
void SysTick_Handler()
{
// SysTick_Handler increments SysTickCnt
SysTickCnt++;
}
void systick_init(void)
{
// Init the systick clocks to a T = 1 ms
RCC_ClocksTypeDef clocks;
RCC_GetClocksFreq(&clocks);
SysTick_Config(clocks.HCLK_Frequency/1000 - 1);
// Set count to 0
SysTickCnt = 0;
}
void Wait(uint32_t ms)
{
// Wait specified time in milliseconds
uint32_t SysTickCntHold = SysTickCnt;
while((SysTickCnt - SysTickCntHold) <= ms);
while((SysTickCnt - SysTickCntHold) <= ms);
}

View file

@ -15,47 +15,27 @@ Für die Tage der offenen Tür der HTBL Hollabrunn im Jahr 2017/18 entstand ein
Das Hauptprogramm in \texttt{main.c} initsialisiert alle Ports sowie den SysTick Interrupt. Die einzelnen Komponenten wurden für die Übersichtlichkeit in extra Files ausgelagert. Im Hauptprogramm ist außerdem der Main-Loop, welcher die Werte vom BMA einliest und am Display ausgibt. Der Main-Loop fragt auch Displayeingaben ab und reagiert auf diese (Start/Stopp, Speichern und Laden).
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: Hauptprogramm, label=lst:sw-odd-main]{Mieke/SW/ODD/main.c}
\subsubsection{io.h}
Dieses Headerfile enthält alle Deklarationen, welche für I/O-Aufgaben des Demoprogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: I/O Headerfile, label=lst:sw-odd-ioh]{Mieke/SW/ODD/io.h}
\subsubsection{io.c}
Dieses C-File enthält die Implementation der I/O Funktionen des Demoprogramms.
Dieses File enthält die Implementation des Input/Output Teils, hauptsächlich initsialisiert sie die einzelnen Peripherieeinheiten, sie stellt aber mit \texttt{USART\_SendString()} auch eine häufig genutzte Funktion zum senden von Strings über UART zuer Verfügung, welche die Standard CMSIS Library nicht beinhaltet.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: I/O Implementation, label=lst:sw-odd-ioc]{Mieke/SW/ODD/io.c}
\subsubsection{display.h}
Dieses Headerfile enthält alle Deklarationen, welche für das Display des Demoprogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: Display Headerfile, label=lst:sw-odd-displayh]{Mieke/SW/ODD/display.h}
\subsubsection{display.c}
Dieses C-File enthält die Implementation der Display Funktionen des Demoprogramms.
In diesem File wird zuerst das Display initsialisiert, danach stellt das File noch Funktionen zum senden von Gyro Daten und zum Aus- und Einschalten bereit. Im File ist auch ein Interrupt-Handler für USART3 ausprogrammiert, welcher Button-Klicks welche das Display sendet verarbeitet und zwischenspeichert, bis sie von einer weiteren Funktion, welche im Main-Loop aufgerufen wird, ausgegeben werden.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: Display Implementation, label=lst:sw-odd-displayc]{Mieke/SW/ODD/display.c}
\subsubsection{bma.h}
Dieses Headerfile enthält alle Deklarationen, welche für das Gyroskop des Demoprogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: BMA Headerfile, label=lst:sw-odd-bmah]{Mieke/SW/ODD/bma.h}
\subsubsection{bma.c}
Dieses C-File enthält die Implementation der BMA Funktionen des Demoprogramms.
Das BMA-File enthält eine Funktion zum auslesen und verarbeiten der drei Beschleunigungsachsen X, Y und Z. Die Funktion wird vom Main Loop aufgerufen und gibt die Beschleunigung auf der übergebenen Pointern bereits für das Display vorverarbeitet (verkleinert und zentriert) zurück.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: BMA Implementation, label=lst:sw-odd-bmac]{Mieke/SW/ODD/bma.c}
\subsubsection{eeprom.h}
Dieses Headerfile enthält alle Deklarationen, welche für das EEPROM des Demoprogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: EEPROM Headerfile, label=lst:sw-odd-eepromh]{Mieke/SW/ODD/eeprom.h}
\subsubsection{eeprom.c}
Dieses C-File enthält die Implementation der EEPROM Funktionen des Demoprogramms.
Dieses File enthält zwi Funktionen, eine zum lesen und eine zum schreiben auf das verbaute EEPROM, beide werden von der Main Loop aufgerufen und erlauben es ein Array von Bytes mit der Länge \texttt{length} ab einer Übergebenen Adresse zu speichern beziehungsweise in dieses zu schreiben.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: EEPROM Implementation, label=lst:sw-odd-eepromc]{Mieke/SW/ODD/eeprom.c}
\subsubsection{bluetooth.h}
Dieses Headerfile enthält alle Deklarationen, welche für die Bluetooth-Signalübertragung des Demoprogramms wichtig sind.
\subsubsection{bluetooth.c}
Das Bluetooth-File enthält eine Funktion zum senden von Gyro Data, welche einen String generiert und diesen über USART1 (wo das Bluetooth Modul angeschlossen ist) ausgibt.
\begin{warning}
Im finalen Programm wurde das Senden der Werte über Bluetooth weggelassen, da es die Main-Loop zu sehr verlangsamte, und somit die Displayausgabe nicht mehr flüssig genug war.
\end{warning}
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: Bluetooth Headerfile, label=lst:sw-odd-bluetoothh]{Mieke/SW/ODD/bluetooth.h}
\subsubsection{bluetooth.c}
Dieses C-File enthält die Implementation der Bluetooth Funktionen des Demoprogramms.
\lstinputlisting[language={[ANSI]C}, caption=Tag der offenen Tür: Bluetooth Implementation, label=lst:sw-odd-bluetoothc]{Mieke/SW/ODD/bluetooth.c}
\subsection{Testprogramm Minimalsystem}
@ -63,82 +43,44 @@ Um die im Unterricht hergestellten Einheiten des \gls{Minimalsystem}s testen zu
\fig{mt-bsb}{Tests: Blockschaltbild}{Tests: Blockschaltbild}{0.75\textwidth}{Mieke/SW/MT/MT}
\subsubsection{main.h}
Einige globale Definitionen.
\lstinputlisting[language={[ANSI]C}, caption=Tests: Hauptprogramm Headerfile, label=lst:sw-mt-mainh]{Mieke/SW/MT/main.h}
\subsubsection{main.c}
Im Hauptprogramm werden die UARTs für das anzeigen der Menüs konfiguriert, die Menüs angezeigt und auf Eingaben auf eben diese reagiert. Die einzelnen Tests wurden möglichst kompakt und modular geschrieben. Ein Test stellt dabei immer ein Interface bestehend aus Init-, Run- und DeInit-Funktion.
Zusätzlich zum C-File existiert auch ein \texttt{main.h}, welches einige globale Variablen, Defines und Typen enthält.
\lstinputlisting[language={[ANSI]C}, caption=Tests: Hauptprogramm, label=lst:sw-mt-main]{Mieke/SW/MT/main.c}
\subsubsection{interface\_uart.h}
Dieses Headerfile enthält alle Deklarationen, welche für das UART Interface des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: UART Headerfile, label=lst:sw-mt-uarth]{Mieke/SW/MT/interface_uart.h}
\subsubsection{interface\_uart.c}
Dieses C-File enthält die Implementation der UART Funktionen des Testpgrogramms.
Dieses File enthält Funktionen um alle USARTs zu initsialisieren, eine Willkommensnachricht an alle zu senden und passend auf die eingabe alle außer einen zu Deaktivieren, dieser verbleibende USART ist dann der, worüber Kommunikation läuft, während alle anderen für Tests zur Verfügung stehen. Des weiteren existieren zwei Funktionen um auf einen neuen Test (beziehungsweise auf eine neue gedrückte Taste) abzufragen. Dies kann entweder blockierend aufgerufen werden, oder nicht blockierend.
\lstinputlisting[language={[ANSI]C}, caption=Tests: UART Implementation, label=lst:sw-mt-uartc]{Mieke/SW/MT/interface_uart.c}
\subsubsection{bma.h}
Dieses Headerfile enthält alle Deklarationen, welche für den BMA Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: BMA Headerfile, label=lst:sw-mt-bmah]{Mieke/SW/MT/bma.h}
\subsubsection{bma.c}
Dieses C-File enthält die Implementation der BMA Test Funktionen des Testpgrogramms.
Der BMA Test, bestehend aus Init und DeInit Funktion und einer Funktion, welche die aktuellen Beschleunigungswerte über ein float-Array ausgibt.
\lstinputlisting[language={[ANSI]C}, caption=Tests: BMA Implementation, label=lst:sw-mt-bmac]{Mieke/SW/MT/bma.c}
\subsubsection{ne555.h}
Dieses Headerfile enthält alle Deklarationen, welche für den NE555 Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: NE555 Headerfile, label=lst:sw-mt-ne555h]{Mieke/SW/MT/ne555.h}
\subsubsection{ne555.c}
Dieses C-File enthält die Implementation der NE555 Test Funktionen des Testpgrogramms.
Der NE555 Test, bestehend aus Init und DeInit Funktion und einer Funktion, welche die Zustandswechsel über eine Sekunde misst und halbiert ausgibt (ergibt eine Frequenz). Dieser Test kann auch für den LFU und den Infrarot Sensor verwendet werden, da die beiden auch Frequenzen ausgeben.
\lstinputlisting[language={[ANSI]C}, caption=Tests: NE555 Implementation, label=lst:sw-mt-ne555c]{Mieke/SW/MT/ne555.c}
\subsubsection{ledswitch.h}
Dieses Headerfile enthält alle Deklarationen, welche für den LED/Switch Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: LED/Switch Headerfile, label=lst:sw-mt-ledswitchh]{Mieke/SW/MT/ledswitch.h}
\subsubsection{ledswitch.c}
Dieses C-File enthält die Implementation der LED/Switch Test Funktionen des Testpgrogramms.
Der LEDs/Switch test liest die Schalterstellungen ein und gibt diese wieder auf den LEDs aus. Bei Verwendung von USART2 kann es hier zu Problemen kommen, da die Schalter unter anderem auf den Rx und Tx Leitungen von USART2 liegen.
\lstinputlisting[language={[ANSI]C}, caption=Tests: LED/Switch Implementation, label=lst:sw-mt-ledswitchc]{Mieke/SW/MT/ledswitch.c}
\subsubsection{eeprom.h}
Dieses Headerfile enthält alle Deklarationen, welche für den EEPROM Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: EEPROM Headerfile, label=lst:sw-mt-eepromh]{Mieke/SW/MT/eeprom.h}
\subsubsection{eeprom.c}
Dieses C-File enthält die Implementation der EEPROM Test Funktionen des Testpgrogramms.
Der EEPROM-Test sendet einige Bytes an den Speicher und liest diese danach sofort wieder aus. Wenn der gesendete und ausgelesene Wert übereinstimmt, dann war der Test erfolgreich.
\lstinputlisting[language={[ANSI]C}, caption=Tests: EEPROM Implementation, label=lst:sw-mt-eepromc]{Mieke/SW/MT/eeprom.c}
\subsubsection{esp.h}
Dieses Headerfile enthält alle Deklarationen, welche für den ESP Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: ESP Headerfile, label=lst:sw-mt-esph]{Mieke/SW/MT/esp.h}
\subsubsection{esp.c}
Dieses C-File enthält die Implementation der ESP Test Funktionen des Testpgrogramms.
Der ESP Test öffnet einen WLAN Access Point und einen TCP Server mit dem Port \texttt{2526}, dieser gibt dann alle Daten, welche mit TCP gesendet werden über den verwendeten USART aus.
\lstinputlisting[language={[ANSI]C}, caption=Tests: ESP Implementation, label=lst:sw-mt-espc]{Mieke/SW/MT/esp.c}
\subsubsection{rgb.h}
Dieses Headerfile enthält alle Deklarationen, welche für den RGB LED Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: RGB LED Headerfile, label=lst:sw-mt-rgbh]{Mieke/SW/MT/rgb.h}
\subsubsection{rgb.c}
Dieses C-File enthält die Implementation der RGB LED Test Funktionen des Testpgrogramms.
Der Test für die RGB LED prüft ob die Kommunikation möglich ist, in dem er die LED bunt blinken lässt.
\lstinputlisting[language={[ANSI]C}, caption=Tests: RGB LED Implementation, label=lst:sw-mt-rgbc]{Mieke/SW/MT/rgb.c}
\subsubsection{piezo.h}
Dieses Headerfile enthält alle Deklarationen, welche für den Piezo Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: Piezo Headerfile, label=lst:sw-mt-piezoh]{Mieke/SW/MT/piezo.h}
\subsubsection{piezo.c}
Dieses C-File enthält die Implementation der Piezo Test Funktionen des Testpgrogramms.
Der Piezo Test gibt einen ton auf eben diesem aus.
\lstinputlisting[language={[ANSI]C}, caption=Tests: Piezo Implementation, label=lst:sw-mt-piezoc]{Mieke/SW/MT/piezo.c}
\subsubsection{display.h}
Dieses Headerfile enthält alle Deklarationen, welche für den Display Test des Testpgrogramms wichtig sind.
\lstinputlisting[language={[ANSI]C}, caption=Tests: Display Headerfile, label=lst:sw-mt-displayh]{Mieke/SW/MT/display.h}
\subsubsection{display.c}
Dieses C-File enthält die Implementation der Display Test Funktionen des Testpgrogramms.
Um das Display zu testen, wird mehrmals der Screen gelöscht und in einer anderen Farbe gezeichnet. Dieser Befehl sollte auch ohne extra Test-Programm, unabhänging von dem zur Zeit geflashten Programm, auf dem Display funktionieren.
\lstinputlisting[language={[ANSI]C}, caption=Tests: Display Implementation, label=lst:sw-mt-displayc]{Mieke/SW/MT/display.c}