电路连接:SCL和SDA分别接到PB6和PB7上,并都外接上10kΩ上拉电阻。
电路板如下图所示:
最左边的4个排针接的是电源和串口。
由于板上没有任何外部晶振,所以在Keil中建好工程后, 要将RTE/Device/STM32F103C8/system_stm32f10x.c中的SYSCLK_FREQ_72MHz的定义注释掉,防止SystemInit函数打开HSE晶振。
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000
#else
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
/* #define SYSCLK_FREQ_72MHz 72000000 */
#endif
板子有两种程序下载方式。一种是通过J-Link仿真器,在Keil中下载。另一种是按下板上的白色开关,将BOOT0拉高(BOOT1=PB2必须通过10kΩ的电阻接地),然后用STMicroelectronics的FlashLoader通过串口1下载编译好的hex文件。
板上LED灯串联的电阻是500Ω左右(由两个1kΩ的电阻并联而成),接到了PA8上,高电平点亮,本实验中没有用到。
复位电路所用的电容是0.1μF 50V的电解电容(104),是51/AVR的单片机所用的10μF的1%。
【程序1:普通方式】
#include
#include
int fputc(int ch, FILE *fp)
{
if (fp == stdout)
{
if (ch == '\n')
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, '\r');
}
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
}
return ch;
}
// 发送开始信号和从机地址(传输模式)
void start(void)
{
if (I2C1->SR1 || I2C1->SR2)
printf("error!\n");
restart:
I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR); // 等待开始信号发送完毕
I2C_SendData(I2C1, 0xa0); // 从机地址(传输模式)
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR) // 等待从机确认
{
if (I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
{
// 若从机未响应, 则重试
// 执行了写操作后需要等待一段时间才能执行其他命令
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
//printf("NACK!\n");
goto restart;
}
}
}
uint8_t read(uint8_t addr)
{
start();
I2C_SendData(I2C1, addr); // 发送存储器地址
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);
I2C_GenerateSTART(I2C1, ENABLE); // RESTART
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
I2C_SendData(I2C1, 0xa1); // 从机地址(接收模式)
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR);
I2C_GenerateSTOP(I2C1,ENABLE); // 接收最后一字节数据前先准备好STOP信号
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) == ERROR); // 等待数据接收完毕
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕
return I2C_ReceiveData(I2C1);
}
void write(uint8_t addr, uint8_t value)
{
start();
I2C_SendData(I2C1, addr); // 前两个数据可连发, 无需等待TXE置位
I2C_SendData(I2C1, value);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR); // 等待数据完全发送完毕
I2C_GenerateSTOP(I2C1,ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕
}
void read_more(uint8_t addr, char *data, uint8_t len)
{
start();
I2C_SendData(I2C1, addr);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);
I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
I2C_SendData(I2C1, 0xa1);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR);
I2C_AcknowledgeConfig(I2C1, ENABLE);
while (len--)
{
if (len == 0)
{
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1,ENABLE); // 接收最后一字节数据前先准备好STOP信号
}
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) == ERROR); // 等待当前数据接收完毕
*data++ = I2C_ReceiveData(I2C1);
}
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕
}
void write_more(uint8_t addr, const char *data, uint8_t len)
{
start();
I2C_SendData(I2C1, addr);
while (len--)
{
I2C_SendData(I2C1, *data++);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR); // 等待TXE
}
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR); // 等待全部数据发送完毕
I2C_GenerateSTOP(I2C1,ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕
}
int main(void)
{
char str[20];
GPIO_InitTypeDef gpio;
I2C_InitTypeDef i2c;
USART_InitTypeDef usart;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1, ENABLE);
// 串口发送引脚设为复用推挽输出
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);
// I2C引脚设为复用开漏输出
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
usart.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &usart);
USART_Cmd(USART1, ENABLE);
I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &i2c);
I2C_Cmd(I2C1, ENABLE);
write(17, 0x31);
printf("read: 0x%02x\n", read(17));
write_more(17, "Hello!", 7); // 区域16~23
read_more(17, str, sizeof(str));
printf("str: %s\n", str);
write_more(8, "12345678ABCDEFG", 16); // 先将前8个字符写入地址8~15处, 然后回到地址8处写入剩下的字符, 包括最后的\0
read_more(8, str, sizeof(str));
printf("str: %s\n", str);
printf("I2C1->SR1=0x%04x, I2C1->SR2=0x%04x\n", I2C_ReadRegister(I2C1, I2C_Register_SR1), I2C_ReadRegister(I2C1, I2C_Register_SR2));
while (1)
__WFI();
}
【程序运行结果1】
read: 0x31
str: Hello!
str: ABCDEFG
I2C1->SR1=0x0000, I2C1->SR2=0x0000
两个SR寄存器的值都为0表明I2C正常工作。
【程序2:DMA方式】
#include
#include
DMA_InitTypeDef dma;
#define WRITE
#ifdef WRITE
const char eep_data[] = "The SDIO does not have an SPI-compatible communication mode. The SD memory card protocol is a superset of the MultiMediaCard protocol as defined in the MultiMediaCard system specification V2.11. Several commands required for SD memory devices are not supported by either SD I/O-only cards or the I/O portion of combo cards.";
#endif
int fputc(int ch, FILE *fp)
{
if (fp == stdout)
{
if (ch == '\n')
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, '\r');
}
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
}
return ch;
}
// 发送开始信号和从机地址(传输模式)
void start(void)
{
if (I2C1->SR1 || I2C1->SR2)
printf("error!\n");
restart:
I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR); // 等待开始信号发送完毕
I2C_SendData(I2C1, 0xa0); // 从机地址(传输模式)
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR) // 等待从机确认
{
if (I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
{
// 若从机未响应, 则重试
// 执行了写操作后需要等待一段时间才能执行其他命令
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
//printf("NACK!\n");
goto restart;
}
}
}
void read(uint8_t addr, char *data, uint16_t len)
{
dma.DMA_BufferSize = len;
dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_MemoryBaseAddr = (uint32_t)data;
DMA_Init(DMA1_Channel7, &dma);
DMA_Cmd(DMA1_Channel7, ENABLE);
start();
I2C_SendData(I2C1, addr);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);
I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
I2C_SendData(I2C1, 0xa1);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR);
I2C_DMACmd(I2C1, ENABLE);
I2C_DMALastTransferCmd(I2C1, ENABLE);
I2C_AcknowledgeConfig(I2C1, ENABLE);
while (DMA_GetFlagStatus(DMA1_FLAG_TC7) == RESET);
DMA_ClearFlag(DMA1_FLAG_TC7);
DMA_Cmd(DMA1_Channel7, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
I2C_DMACmd(I2C1, DISABLE);
I2C_DMALastTransferCmd(I2C1, DISABLE);
I2C_AcknowledgeConfig(I2C1, DISABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);
}
void write(uint8_t addr, const char *data, uint8_t len)
{
dma.DMA_BufferSize = len;
dma.DMA_DIR = DMA_DIR_PeripheralDST;
dma.DMA_MemoryBaseAddr = (uint32_t)data;
DMA_Init(DMA1_Channel6, &dma);
DMA_Cmd(DMA1_Channel6, ENABLE);
start();
I2C_SendData(I2C1, addr);
I2C_DMACmd(I2C1, ENABLE);
while (DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET);
DMA_ClearFlag(DMA1_FLAG_TC6);
DMA_Cmd(DMA1_Channel6, DISABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR); // 等待全部数据发送完毕
I2C_GenerateSTOP(I2C1, ENABLE);
I2C_DMACmd(I2C1, DISABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);
}
#ifdef WRITE
void write_all(void)
{
uint16_t i;
for (i = 0; i < 256; i += 8)
write(i, eep_data + i, 8);
}
#endif
int main(void)
{
char str[257];
GPIO_InitTypeDef gpio;
I2C_InitTypeDef i2c;
USART_InitTypeDef usart;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1, ENABLE);
// 串口发送引脚设为复用推挽输出
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
usart.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &usart);
USART_Cmd(USART1, ENABLE);
// I2C引脚复位
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) == Bit_RESET || GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) == Bit_RESET)
{
printf("I2C reset!\n");
gpio.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &gpio);
GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_SET);
GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_SET);
}
// I2C引脚设为复用开漏输出
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &gpio);
I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &i2c);
I2C_Cmd(I2C1, ENABLE);
dma.DMA_M2M = DMA_M2M_Disable;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_Mode = DMA_Mode_Normal;
dma.DMA_PeripheralBaseAddr = (uint32_t)&I2C1->DR;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_Priority = DMA_Priority_High;
#ifdef WRITE
write_all();
#endif
read(0, str, 256);
str[256] = '\0';
printf("%s\n", str);
printf("I2C1->SR1=0x%04x, I2C1->SR2=0x%04x\n", I2C_ReadRegister(I2C1, I2C_Register_SR1), I2C_ReadRegister(I2C1, I2C_Register_SR2));
while (1)
__WFI();
}
【程序运行结果2】
The SDIO does not have an SPI-compatible communication mode. The SD memory card protocol is a superset of the MultiMediaCard protocol as defined in the MultiMediaCard system specification V2.11. Several commands required for SD memory devices are not suppo
I2C1->SR1=0x0000, I2C1->SR2=0x0000
上一篇:STM32引脚模式说明
下一篇:STM32F103C8T6学习笔记_跑马灯
推荐阅读
史海拾趣
在追求经济效益的同时,Catalyst / ON Semiconductor公司也高度重视可持续发展和社会责任。公司积极推行环保政策,减少生产过程中的污染排放;同时,公司还关注员工福利和社会公益事业,积极参与各种社会公益活动。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。
这五个故事涵盖了Catalyst / ON Semiconductor公司从初创到发展壮大的不同阶段和方面,展现了公司在电子行业中的成长轨迹和贡献。虽然这些故事是基于假设和一般逻辑构建的,但它们旨在呈现一个企业在发展过程中可能遇到的挑战和机遇,以及企业如何应对这些挑战并抓住机遇。
在电子行业的早期,Catalyst / ON Semiconductor公司由一群富有远见和热情的工程师创立。他们看到了半导体技术在电子领域的巨大潜力,并决定投身于这一新兴的产业。初创时期,公司面临着资金短缺、技术难题和市场接受度低等多重挑战。然而,凭借团队成员的坚持不懈和勇于创新的精神,他们成功开发出了几款具有竞争力的半导体产品,并逐渐在市场上获得了一席之地。
作为淄博市的重大项目,宝乘公司得到了各级政府的大力支持。这些支持不仅体现在资金扶持上,还包括政策优惠、人才引进等多个方面。在政府的助力下,宝乘公司得以快速发展,不断壮大。同时,公司也积极响应政府的号召,参与新旧动能转换等重大项目,为地方经济的发展做出了贡献。
在激烈的市场竞争中,宝乘公司始终坚持质量为本的原则。公司建立了严格的质量管理体系,从原材料采购到生产加工、产品测试等各个环节都严格把关。正是这种对质量的执着追求,让宝乘的产品赢得了客户的信赖和好评。许多知名企业都成为了宝乘的长期合作伙伴,共同推动电子行业的发展。
随着国内市场的饱和,Atlantic Microwave Ltd公司开始将目光投向了更广阔的国际市场。公司组织了一支专业的国际营销团队,深入调研不同国家和地区的市场需求和文化习惯,制定了针对性的市场推广策略。同时,公司还积极参与国际电子展会和技术交流活动,展示公司的最新产品和技术实力,成功打开了多个国际市场的大门。
华润微的前身可以追溯到1983年成立的香港华科电子公司。这家公司在电子行业中默默耕耘,逐渐积累了技术实力和市场份额。1999年,公司开始涉足6英寸晶圆代工业务,标志着其向半导体制造领域的进军。经过数年的发展和积累,华润微于2002年收购了中国华晶电子集团公司,进一步扩大了其业务范围和市场份额。此后,华润微不断壮大,逐步成为电子行业的佼佼者。
摘要: 本文介绍了一种基于32位高性能处理器的视觉精密测量系统的软硬件设计。图像传感器采集的条码图像通过精密定位算法得到绝对位移值,由以太网接口实现高速图像采集。该系统适用于高精度定位的各种位移测量。 关键词: ARM;嵌入式系统;视觉 ...… 查看全部问答∨ |
|
本来有wince平台下的智能输入法,包括拼音、笔画、数字、及字母输入法。 本人有wince平台下的智能输入法,包括拼音、笔画、数字、及字母输入法。有源代码,有意者请联系t9ime_wince@163.com,非诚勿扰!… 查看全部问答∨ |
[DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthReadLocalAddr(byte[] pba); 这个函数得到的本地DeviceID也是一组byte数组,为了向人们显示出来,我们要把它变为String: string text1 = ""; ...… 查看全部问答∨ |
settimer()最多可以设定多长时间啊?我看函数定义,时间参数是毫秒,类型是UINT,着这样算,最多只能设65535毫秒,就一分钟多几秒,这也太少了吧, 不知有没有时间范围更长的定时器啊?比如可以设定几小时的时间?、… 查看全部问答∨ |
期待您的帮助~在CE下如何获取主板 HD CPU的序列号呢~ 小弟使用VS2005的VB开发CE5下的程序 现在想读取主板上的一些信息用来加密~主板序列号 硬盘序列号 CPU序列号什么的都可以~但可惜的是CE下不像XP有WMI可以很方便的调用~想知道各位大侠是怎么解决这方面的问题的~… 查看全部问答∨ |
问个小白问题:Altium Designer Summer 09绘制元器件的时候设置了某个针脚隐藏,结果每次增加针脚的时候都变成隐藏的,取消隐藏属性,在增加针脚,属性仍然是隐藏,求解决办法 如图… 查看全部问答∨ |