冰楓論壇

標題: STM8S103F3 [打印本頁]

作者: 洪嵐峰    時間: 2023-4-24 21:02
標題: STM8S103F3
以下是使用STM8S103F3微控制器製作點焊機

所需零件
STM8S103F3微控制器開發板
16x2字符LCD顯示器
MAX6675溫度感應器模塊
端子塊(用於連接加熱器、感應器和控制信號)
加熱器
電源供應器
電阻、電容等基本元件
連接腳位
以下是STM8S103F3微控制器和其他元件之間的連接腳位示意圖:

markdown
Copy code
STM8S103F3         MAX6675          16x2 LCD          端子塊
     PA1             SCK
     PA2             SO
     PD2                                          控制信號
     PC3                                          溫度感應器
     PA3                                          加熱器
程式碼
以下是使用SDCC編譯器和STM8S標準庫編寫的示例程式碼:


#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stm8s.h>

#define PULSE_WIDTH 5000 //焊接脈衝寬度,以微秒為單位
#define WAIT_TIME 10000 //等待時間,以微秒為單位

#define RS_PIN GPIO_PIN_3
#define EN_PIN GPIO_PIN_2
#define D4_PIN GPIO_PIN_5
#define D5_PIN GPIO_PIN_6
#define D6_PIN GPIO_PIN_7
#define D7_PIN GPIO_PIN_0

#define LCD_CMD_CLEAR_DISPLAY 0x01
#define LCD_CMD_RETURN_HOME 0x02
#define LCD_CMD_ENTRY_MODE_SET 0x04
#define LCD_CMD_DISPLAY_ON_OFF_CONTROL 0x08
#define LCD_CMD_CURSOR_DISPLAY_SHIFT 0x10
#define LCD_CMD_FUNCTION_SET 0x20
#define LCD_CMD_SET_CGRAM_ADDRESS 0x40
#define LCD_CMD_SET_DDRAM_ADDRESS 0x80

#define LCD_DISPLAY_ON 0x04
#define LCD_CURSOR_ON 0x02
#define LCD_BLINK_ON 0x01

#define LCD_ENTRY_MODE_INCREMENT 0x02
#define LCD_ENTRY_MODE_DISPLAY_SHIFT 0x01

#define LCD_FUNCTION_SET_4BIT 0x00
#define LCD_FUNCTION_SET_2LINE 0x08
#define LCD_FUNCTION_SET_5X8DOTS 0x00

#define LCD_LINE1 0x00
#define LCD_LINE2 0x40

#define LCD_DATA 1
#define LCD_CMD 0

void delay_us(uint32_t us)
{
    uint32_t count = us * (SystemCoreClock / 1000000) / 5;
    while (count--);
}

void lcd_send_nibble(uint8_t nibble, uint8_t rs)
{
    GPIO_WriteLow(GPIOB, RS_PIN);
    if (rs) {
        GPIO_WriteHigh(GPIOB, RS_PIN);
    }
    GPIO_WriteLow(GPIOB, EN_PIN);
    GPIO_WriteLow(GPIOB, D4_PIN);
    GPIO_WriteLow
    GPIO_WriteLow(GPIOB, D5_PIN);
    GPIO_WriteLow(GPIOB, D6_PIN);
    GPIO_WriteLow(GPIOB, D7_PIN);
    if (nibble & 0x10) {
    GPIO_WriteHigh(GPIOB, D4_PIN);
}
if (nibble & 0x20) {
    GPIO_WriteHigh(GPIOB, D5_PIN);
}
if (nibble & 0x40) {
    GPIO_WriteHigh(GPIOB, D6_PIN);
}
if (nibble & 0x80) {
    GPIO_WriteHigh(GPIOB, D7_PIN);
}
delay_us(1);
GPIO_WriteHigh(GPIOB, EN_PIN);
delay_us(1);
GPIO_WriteLow(GPIOB, EN_PIN);
}

void lcd_send_byte(uint8_t data, uint8_t rs)
{
lcd_send_nibble(data >> 4, rs);
lcd_send_nibble(data & 0x0F, rs);
delay_us(50);
}

void lcd_init()
{
delay_us(15000);
lcd_send_nibble(0x30, LCD_CMD);
delay_us(4500);
lcd_send_nibble(0x30, LCD_CMD);
delay_us(150);
lcd_send_nibble(0x30, LCD_CMD);
delay_us(150);
lcd_send_nibble(0x20, LCD_CMD);
lcd_send_byte(LCD_FUNCTION_SET_4BIT | LCD_FUNCTION_SET_2LINE | LCD_FUNCTION_SET_5X8DOTS, LCD_CMD);
lcd_send_byte(LCD_DISPLAY_ON | LCD_CURSOR_ON | LCD_BLINK_ON, LCD_CMD);
lcd_send_byte(LCD_CMD_CLEAR_DISPLAY, LCD_CMD);
lcd_send_byte(LCD_ENTRY_MODE_SET | LCD_ENTRY_MODE_INCREMENT | LCD_ENTRY_MODE_DISPLAY_SHIFT, LCD_CMD);
}

void lcd_puts(const char* str)
{
while (*str) {
lcd_send_byte(*str++, LCD_DATA);
}
}

void lcd_goto(uint8_t line, uint8_t pos)
{
lcd_send_byte(LCD_CMD_SET_DDRAM_ADDRESS | (line ? LCD_LINE2 : LCD_LINE1) | pos, LCD_CMD);
}

uint16_t read_adc()
{
uint16_t result = 0;
ADC1->CSR |= ADC1_CSR_EOCIE;
ADC1->CR1 |= ADC1_CR1_ADON;
while (!(ADC1->CSR & ADC1_CSR_EOC));
result = ADC1->DRL;
result |= (uint16_t)ADC1->DRH << 8;
ADC1->CSR &= ~ADC1_CSR_EOCIE;
return result;
}

void setup_gpio()
{
GPIO_Init(GPIOB, RS_PIN | EN_PIN | D4_PIN | D5_PIN | D6_PIN | D7_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);
}

void setup_adc()
{
ADC1->CR2 |= ADC1_CR2_TSVREFE;
ADC1->CR1 |= ADC1_CR1_ADON;
delay_us(20);
ADC1->CR1 |= ADC1_CR1_ADON;
delay_us(20);
}

void setup_timer()
{
TIM1->PSCRH = 0;
TIM1->PSCRL = 7;
TIM1->ARRH = 0;
TIM1->ARRL = 255

TIM1->CCMR1 |= TIM1_CCMR1_OC1M_2 | TIM1_CCMR1_OC1M_1;
TIM1->CCER1 |= TIM1_CCER1_CC1E;
TIM1->BKR |= TIM1_BKR_MOE;
TIM1->CR1 |= TIM1_CR1_CEN;
}

void setup_interrupts()
{
EXTI->CR1 |= EXTI_CR1_PCIS;
EXTI->CR2 |= EXTI_CR2_TLIS;
ITC_SetSoftwarePriority(EXTI_PORTC, ITC_PRIORITYLEVEL_3);
ITC_SetSoftwarePriority(EXTI_PORTD, ITC_PRIORITYLEVEL_4);
ITC_SetSoftwarePriority(TIM1_UPD_OVF_TRG_BRK_IRQn, ITC_PRIORITYLEVEL_2);
enableInterrupts();
}

void setup()
{
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
setup_gpio();
setup_adc();
setup_timer();
setup_interrupts();
lcd_init();
}

void loop()
{
static uint32_t last_read_time = 0;
static uint16_t last_read_value = 0;
static uint8_t error_count = 0;
uint16_t value = read_adc();
if (value == last_read_value) {
if ((millis() - last_read_time) > 5000) {
error_count++;
if (error_count > 3) {
GPIOD->ODR ^= GPIO_PIN_2;
lcd_goto(1, 0);
lcd_puts("ERROR: SENSOR");
lcd_goto(2, 0);
lcd_puts("DISCONNECTED ");
error_count = 0;
}
}
} else {
error_count = 0;
last_read_time = millis();
last_read_value = value;
}
uint16_t duty_cycle = (value * 255) / 1023;
TIM1->CCR1H = duty_cycle >> 8;
TIM1->CCR1L = duty_cycle & 0xFF;
}

void main()
{
setup();
while (1) {
loop();
}
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1);
}
#endif

在上述程式碼中,使用了STM8S103F3微控制器來控制點焊機。

以下是程式碼各個部分功能:

setup_gpio(): 設定GPIO腳位的方向,以便控制機器的電磁鐵、蜂鳴器和LED指示燈。

setup_adc(): 設定ADC輸入,以便讀取感測器的輸出。

setup_timer(): 設定計時器,以便產生PWM信號,控制點焊機的加熱時間。

setup_interrupts(): 設定中斷,以便在ADC輸入發生變化時及計時器產生溢出時進行處理。

setup(): 設定系統時鐘,調用setup_gpio()、setup_adc()、setup_timer()和setup_interrupts()函數,初始化LCD顯示器。

loop(): 不斷讀取ADC輸入,並使用PWM信號控制點焊機的加熱時間。

如果ADC輸入未發生變化,且時間超過5秒,則判斷為感測器斷線,顯示錯誤信息。

main(): 調用setup()函數,然後不斷調用loop()函數。

除了上述函數外,程式碼還包含了斷言失敗的處理函數。

程式碼還使用了一些宏定義和STM8庫函數,例如millis(),它可以返回從系統啟動以來的毫秒數。




歡迎光臨 冰楓論壇 (https://bingfong.com/) Powered by 冰楓