前言
**本程序设计是基于嵌入式开发板CT117E,stm32f103RBT6。
如果对哪个模块的代码不理解可以点开我的博客查看各个模块的编写思路。
一、试题
二、需要用到的模块
1.LED灯
led.c:
#include "led.h"
void led_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
/* Configure PD0 and PD2 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIOC->ODR |= (0XFF<<8);
GPIOD->ODR |= (0X01<<2);
GPIOD->ODR &= ~(0X01<<2);
}
void led_ctrl(u8 ledx,u8 status)
{
if(status)
{
GPIOC->ODR &= ~(0X01<<ledx);
GPIOD->ODR |= (0X01<<2);
GPIOD->ODR &= ~(0X01<<2);
}
else
{
GPIOC->ODR |= (0X01<<ledx);
GPIOD->ODR |= (0X01<<2);
GPIOD->ODR &= ~(0X01<<2);
}
}
led.h:
#ifndef LED_H
#define LED_H
#include "stm32f10x.h"
void led_init(void);
void led_ctrl(u8 ledx,u8 status);
#endif
2.ADC按键
代码如下:adc_key.c:
#include "adc_key.h"
void adc_key_init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure PC.01, PC.02 and PC.04 (ADC Channel11, Channel12 and Channel14)
as analog input ----------------------------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration */
//ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
u8 get_key(u8 channel)
{
u16 s[50];
u8 i,j;
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);
for(i=0;i<51;i++)
{
s[i]=ADC_GetConversionValue(ADC1);
}
ADC_SoftwareStartConvCmd(ADC1,DISABLE);
for(i=0;i<51-1;i++)
{
for(j=0;j<51-i-1;j++)
{
if(s[j]>s[j+1])
{
s[j]=s[j]^s[j+1];
s[j+1]=s[j]^s[j+1];
s[j]=s[j]^s[j+1];
}
}
}
if(s[25]<0x015) return 1;
else if(s[25]<0x250) return 2;
else if(s[25]<0x500) return 3;
else if(s[25]<0x700) return 4;
else if(s[25]<0xA00) return 5;
else if(s[25]<0xC00) return 6;
else if(s[25]<0xE00) return 7;
else if(s[25]<0xFC0) return 8;
else return 0;
}
adc_key.h:
#ifndef ADC_KEY_H
#define ADC_KEY_H
#include "stm32f10x.h"
void adc_key_init(void);
u8 get_key(u8 channel);
#endif
3.ADC
代码如下:adc.c:
#include "adc.h"
void adc_init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure PC.01, PC.02 and PC.04 (ADC Channel11, Channel12 and Channel14)
as analog input ----------------------------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration */
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
u16 get_adc(u8 channel)
{
u16 s[50];
u8 i,j;
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);
for(i=0;i<51;i++)
{
s[i]=ADC_GetConversionValue(ADC1);
}
ADC_SoftwareStartConvCmd(ADC1,DISABLE);
for(i=0;i<51-1;i++)
{
for(j=0;j<51-i-1;j++)
{
if(s[j]>s[j+1])
{
s[j]=s[j]^s[j+1];
s[j+1]=s[j]^s[j+1];
s[j]=s[j]^s[j+1];
}
}
}
return s[25];
}
adc.h:
#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
void adc_init(void);
u16 get_adc(u8 channel);
#endif
4.串口
代码如下:usart.c:
#include "usart.h"
void usart_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USARTy */
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
}
void sent_data(u8 *s)
{
do
{
USART_SendData(USART2,*s++);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==0);
}while(*s);
}
usart.h:
#ifndef USART_H
#define USART_H
#include "stm32f10x.h"
void usart_init(void);
void sent_data(u8 *s);
#endif
5.i2c
i2c.c
/*
程序说明: CT117E嵌入式竞赛板GPIO模拟I2C总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT117E嵌入式竞赛板
日 期: 2011-8-9
*/
#include "stm32f10x.h"
#include "i2c.h"
/** I2C 总线接口 */
#define I2C_PORT GPIOB
#define SDA_Pin GPIO_Pin_7
#define SCL_Pin GPIO_Pin_6
#define FAILURE 0
#define SUCCESS 1
//配置SDA信号线为输入模式
void SDA_Input_Mode()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//配置SDA信号线为输出模式
void SDA_Output_Mode()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//
void SDA_Output( uint16_t val )
{
if ( val ) {
GPIO_SetBits(I2C_PORT,SDA_Pin);
} else {
GPIO_ResetBits(I2C_PORT,SDA_Pin);
}
}
//
void SCL_Output( uint16_t val )
{
if ( val ) {
GPIO_SetBits(I2C_PORT,SCL_Pin);
} else {
GPIO_ResetBits(I2C_PORT,SCL_Pin);
}
}
uint8_t SDA_Input()
{
return GPIO_ReadInputDataBit( I2C_PORT, SDA_Pin);
}
void delay1(unsigned int n)
{
unsigned int i;
for ( i=0;i<n;++i);
}
//I2C总线启动
void I2CStart(void)
{
SDA_Output(1);delay1(500);
SCL_Output(1);delay1(500);
SDA_Output(0);delay1(500);
SCL_Output(0);delay1(500);
}
void I2CStop(void)
{
SCL_Output(0); delay1(500);
SDA_Output(0); delay1(500);
SCL_Output(1); delay1(500);
SDA_Output(1); delay1(500);
}
//等待应答
unsigned char I2CWaitAck(void)
{
unsigned short cErrTime = 5;
SDA_Input_Mode();
delay1(500);
SCL_Output(1);delay1(500);
while(SDA_Input())
{
cErrTime--;
delay1(500);
if (0 == cErrTime)
{
SDA_Output_Mode();
I2CStop();
return FAILURE;
}
}
SDA_Output_Mode();
SCL_Output(0);delay1(500);
return SUCCESS;
}
void I2CSendAck(void)
{
SDA_Output(0);delay1(500);
delay1(500);
SCL_Output(1); delay1(500);
SCL_Output(0); delay1(500);
}
void I2CSendNotAck(void)
{
SDA_Output(1);
delay1(500);
SCL_Output(1); delay1(500);
SCL_Output(0); delay1(500);
}
//通过I2C总线发送一个字节数据
void I2CSendByte(unsigned char cSendByte)
{
unsigned char i = 8;
while (i--)
{
SCL_Output(0);delay1(500);
SDA_Output(cSendByte & 0x80); delay1(500);
cSendByte += cSendByte;
delay1(500);
SCL_Output(1);delay1(500);
}
SCL_Output(0);delay1(500);
}
//从I2C总线接收一个字节数据
unsigned char I2CReceiveByte(void)
{
unsigned char i = 8;
unsigned char cR_Byte = 0;
SDA_Input_Mode();
while (i--)
{
cR_Byte += cR_Byte;
SCL_Output(0);delay1(500);
delay1(500);
SCL_Output(1);delay1(500);
cR_Byte |= SDA_Input();
}
SCL_Output(0);delay1(500);
SDA_Output_Mode();
return cR_Byte;
}
//I2C总线初始化
void i2c_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // **
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
void i2c_write(u8 addr,u8 data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
u8 i2c_read(u8 addr)
{
u8 t;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
t=I2CReceiveByte();
I2CWaitAck();
I2CStop();
return t;
}
i2c.h
#ifndef __I2C_H__
#define __I2C_H__
void i2c_init(void);
void delay1(unsigned int n);
void I2CStart(void);
void I2CStop(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
unsigned char I2CWaitAck(void);
void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
void i2c_write(u8 addr,u8 data);
u8 i2c_read(u8 addr);
#endif
三、主函数逻辑设计
stm32f10x_it.c:
#include "stm32f10x_it.h"
extern u32 TimingDelay;
extern u8 key_flag;
extern u8 led_flag1,led_flag2;
void SysTick_Handler(void)
{
static u8 key_num=0 ;
static u16 ms_800=0, ms_400=0;
key_num++;
ms_800++;
ms_400++;
if(key_num==50)
{
key_flag=1;
key_num=0;
}
if(ms_400==400)
{
led_flag1 ^=1;
ms_400=0;
}
if(ms_800==800)
{
led_flag2 ^=1;
ms_800=0;
}
TimingDelay--;
}
main.c:
#include "stm32f10x.h"
#include "stdio.h"
#include "lcd.h"
#include "led.h"
#include "adc.h"
#include "adc_key.h"
#include "i2c.h"
#include "usart.h"
u32 TimingDelay = 0;
u8 buff[20]; //拷贝数据缓冲区
void Delay_Ms(u32 nTime);
u16 adc_val; //接收12位的ADC值
float kg; //存放重量变量
u8 key_flag; //每50ms刷新一次,用于按键的消抖
u8 key4_flag=1; //按键4按下的标志
u8 key; //存放当前按键值
u8 n=1; //记录货物编号
u8 key1_flag=1; //按键1按下标志
u8 key_num[8]; //存放按键按下的计数值
u8 num=0; //存放设置的次数
u8 led_flag1,led_flag2; //led闪的频率 400ms,800ms
float all_price; //总价
float price[3]={0.20,0.20,0.30}; //单价
u8 usart_buff[20];
void lcd_show(void);
void key_read(void);
float i2c_float_read(u8 addr);
void i2c_float_write(u8 addr,float data); //2位小数的写入
//Main Body
int main(void)
{
SysTick_Config(SystemCoreClock/1000);
Delay_Ms(200);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
led_init();
adc_init();
adc_key_init();
i2c_init();
usart_init();
//sent_data("\n");
if(i2c_read(0x19)!=8)
{
i2c_write(0x19,8);
Delay_Ms(5);
i2c_write(0x20,num);
Delay_Ms(5);
i2c_float_write(0x24,price[0]);
Delay_Ms(2);
i2c_float_write(0x30,price[1]);
Delay_Ms(2);
i2c_float_write(0x40,price[2]);
Delay_Ms(2);
}
num=i2c_read(0x20);
Delay_Ms(5);
price[0]=i2c_float_read(0x24);
Delay_Ms(5);
price[1]=i2c_float_read(0x30);
Delay_Ms(2);
price[2]=i2c_float_read(0x40);
Delay_Ms(2);
while(1)
{
if(led_flag1)
{
adc_val=get_adc(ADC_Channel_4);
kg=(float)adc_val/0xfff*10.00;
if(kg>9.95)
{
kg=10;
}
if(kg<0.03)
{
kg=0;
}
}
if(key_flag)
{
key=get_key(ADC_Channel_5);
key_read();
key_flag=0;
}
lcd_show();
}
}
//
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void key_read(void)
{
if(key==1)
{
key_num[0]++;
}
else
{
if(key_num[0]>1 && key_num[0]<10)
{
key1_flag ^=1;
if(key1_flag==0)
{
num++;
}
if(key1_flag==1)
{
i2c_write(0x20,num);
Delay_Ms(5);
i2c_float_write(0x24,price[0]);
Delay_Ms(5);
i2c_float_write(0x30,price[1]);
Delay_Ms(5);
i2c_float_write(0x40,price[2]);
Delay_Ms(5);
sprintf((char *)usart_buff,"U.W.1:%0.2f\n",price[0]);
sent_data(usart_buff);
sprintf((char *)usart_buff,"U.W.2:%0.2f\n",price[1]);
sent_data(usart_buff);
sprintf((char *)usart_buff,"U.W.3:%0.2f\n",price[2]);
sent_data(usart_buff);
}
}
key_num[0]=0;
}
/
if(key==2 && key1_flag==0)
{
key_num[1]++;
if(key_num[1]>16)
{
switch(key4_flag)
{
case 1: price[0] =price[0] +0.01;
if(price[0]>10)
{
price[0]=10;
}
break;
case 2: price[1] =price[1]+0.01;
if(price[1]>10)
{
price[1]=10;
}
break;
case 3: price[2] =price[2] +0.01;
if(price[2]>10)
{
price[2]=10;
}
break;
default: break;
}
}
}
else
{
if(key_num[1]>1 && key_num[1]<10)
{
switch(key4_flag)
{
case 1: price[0] +=0.01;
if(price[0]>10)
{
price[0]=10;
}
break;
case 2: price[1] +=0.01;
if(price[1]>10)
{
price[1]=10;
}
break;
case 3: price[2] +=0.01;
if(price[2]>10)
{
price[2]=10;
}
break;
default: break;
}
}
key_num[1]=0;
}
/
if(key==3 && key1_flag==0)
{
key_num[2]++;
if(key_num[2]>16)
{
switch(key4_flag)
{
case 1: price[0] -=0.01;
if(price[0]<0)
{
price[0]=0;
}
break;
case 2: price[1] -=0.01;
if(price[1]<0)
{
price[1]=0;
}
break;
case 3: price[2] -=0.01;
if(price[2]<0)
{
price[2]=0;
}
break;
default: break;
}
}
}
else
{
if(key_num[2]>1 && key_num[2]<10)
{
switch(key4_flag)
{
case 1: price[0] -=0.01;
if(price[0]<0)
{
price[0]=0;
}
break;
case 2: price[1] -=0.01;
if(price[1]<0)
{
price[1]=0;
}
break;
case 3: price[2] -=0.01;
if(price[2]<0)
{
price[2]=0;
}
break;
default: break;
}
}
key_num[2]=0;
}
/
if(key==4)
{
key_num[3]++;
}
else
{
if(key_num[3]>1 && key_num[3]<10)
{
key4_flag++;
if(key4_flag>3)
{
key4_flag=1;
}
}
key_num[3]=0;
}
/
if(key==5)
{
key_num[4]++;
}
else
{
if(key_num[4]>1 && key_num[4]<10)
{
n=1;
}
key_num[4]=0;
}
/
if(key==6)
{
key_num[5]++;
}
else
{
if(key_num[5]>1 && key_num[5]<10)
{
n=2;
}
key_num[5]=0;
}
/
if(key==7)
{
key_num[6]++;
}
else
{
if(key_num[6]>1 && key_num[6]<10)
{
n=3;
}
key_num[6]=0;
}
/
if(key==8)
{
key_num[7]++;
}
else
{
if(key_num[7]>1 && key_num[7]<10)
{
all_price=kg*price[n-1];
sprintf((char *)usart_buff,"U.W.%d:%0.2f\n",n,price[n-1]);
sent_data(usart_buff);
sprintf((char *)usart_buff,"G.W:%0.2f\n",kg);
sent_data(usart_buff);
sprintf((char *)usart_buff,"Total:%0.2f\n",all_price);
sent_data(usart_buff);
}
key_num[7]=0;
}
}
void lcd_show(void)
{
if(key1_flag)
{
led_ctrl(8,led_flag2);
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line1," Main ");
sprintf((char *)buff," Num : %d ",n);
LCD_DisplayStringLine(Line3,buff);
sprintf((char *)buff," Cost : %0.2f/kg ",price[n-1]);
LCD_DisplayStringLine(Line4,buff);
sprintf((char *)buff," Weight: %0.2fkg ",kg);
LCD_DisplayStringLine(Line5,buff);
sprintf((char *)buff," Price : %0.2f ",all_price);
LCD_DisplayStringLine(Line6,buff);
LCD_DisplayStringLine(Line8," d");
}
else
{
led_ctrl(8,led_flag1);
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line1," Setting ");
if(key4_flag==1)
{
LCD_SetBackColor(Green);
}
else
{
LCD_SetBackColor(Blue);
}
sprintf((char *)buff," Goods1 :%0.2f/kg ",price[0]);
LCD_DisplayStringLine(Line3,buff);
if(key4_flag==2)
{
LCD_SetBackColor(Green);
}
else
{
LCD_SetBackColor(Blue);
}
sprintf((char *)buff," Goods2 :%0.2f/kg ",price[1]);
LCD_DisplayStringLine(Line4,buff);
if(key4_flag==3)
{
LCD_SetBackColor(Green);;
}
else
{
LCD_SetBackColor(Blue);
}
sprintf((char *)buff," Goods3 :%0.2f/kg ",price[2]);
LCD_DisplayStringLine(Line5,buff);
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line6," ");
sprintf((char *)buff," Num:%d ",num);
LCD_DisplayStringLine(Line8,buff);
}
}
float i2c_float_read(u8 addr)
{
float t;
t =(i2c_read(addr))<<8;
Delay_Ms(5);
t +=i2c_read(addr+1);
Delay_Ms(5);
return t/100;
}
void i2c_float_write(u8 addr,float data) //2位小数的写入
{
u32 t;
t=100*data;
i2c_write(addr,t>>8);
Delay_Ms(5);
i2c_write(addr+1,t&0xff);
Delay_Ms(5);
}
四、 代码测试结果图
①主测试界面:
按下计费键,发送计费数据到串口
②设置界面
返回主界面,发送单价数据到串口